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

NACP changes.

Fixed types for some NACP struct entries (thanks @0Liam !) + added functions to generate and write NACP patches.
This commit is contained in:
Pablo Curiel 2020-10-28 18:48:46 -04:00
parent 2b8e80c283
commit 0229124173
11 changed files with 185 additions and 101 deletions

View file

@ -47,8 +47,11 @@ typedef struct {
static options_t options[] = {
{ "set download distribution type", false },
{ "remove console specific data", false },
{ "remove titlekey crypto (implies previous option)", false },
{ "change acid rsa key/sig", false }
{ "remove titlekey crypto (overrides previous option)", false },
{ "change acid rsa key/sig", false },
{ "disable linked account requirement", false },
{ "enable screenshots", false },
{ "enable video capture", false }
};
static const u32 options_count = MAX_ELEMENTS(options);
@ -85,7 +88,14 @@ static void nspDump(TitleInfo *title_info)
for(u32 i = 0; i < options_count; i++) printf("%s: %s\n", options[i].str, options[i].val ? "yes" : "no");
printf("______________________________\n\n");
bool set_download_type = options[0].val, remove_console_data = options[1].val, remove_titlekey_crypto = options[2].val, change_acid_rsa = options[3].val, success = false;
bool set_download_type = options[0].val;
bool remove_console_data = options[1].val;
bool remove_titlekey_crypto = options[2].val;
bool change_acid_rsa = options[3].val;
bool patch_sua = options[4].val;
bool patch_screenshot = options[5].val;
bool patch_video_capture = options[6].val;
bool success = false;
u8 *buf = NULL;
char *dump_name = NULL, *path = NULL;
@ -263,7 +273,11 @@ static void nspDump(TitleInfo *title_info)
goto end;
}
// add nacp mods here
if (!nacpGenerateNcaPatch(cur_nacp_ctx, patch_sua, patch_screenshot, patch_video_capture))
{
consolePrint("nacp nca patch failed (%s)\n", cur_nca_ctx->content_id_str);
goto end;
}
if (!nacpGenerateAuthoringToolXml(cur_nacp_ctx, title_info->version.value, cnmtGetRequiredTitleVersion(&cnmt_ctx)))
{
@ -505,18 +519,13 @@ static void nspDump(TitleInfo *title_info)
switch(cur_nca_ctx->content_type)
{
case NcmContentType_Meta:
{
cnmtWriteNcaPatch(&cnmt_ctx, buf, blksize, offset);
break;
}
case NcmContentType_Program:
{
ProgramInfoContext *cur_program_info_ctx = (ProgramInfoContext*)cur_nca_ctx->content_type_ctx;
programInfoWriteNcaPatch(cur_program_info_ctx, buf, blksize, offset);
programInfoWriteNcaPatch((ProgramInfoContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;
}
case NcmContentType_Control:
// write nacp patches here
nacpWriteNcaPatch((NacpContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;
default:
break;

View file

@ -46,8 +46,11 @@ typedef struct {
static options_t options[] = {
{ "set download distribution type", false },
{ "remove console specific data", false },
{ "remove titlekey crypto (implies previous option)", false },
{ "change acid rsa key/sig", false }
{ "remove titlekey crypto (overrides previous option)", false },
{ "change acid rsa key/sig", false },
{ "disable linked account requirement", false },
{ "enable screenshots", false },
{ "enable video capture", false }
};
static const u32 options_count = MAX_ELEMENTS(options);
@ -84,7 +87,13 @@ static void nspDump(TitleInfo *title_info)
for(u32 i = 0; i < options_count; i++) printf("%s: %s\n", options[i].str, options[i].val ? "yes" : "no");
printf("______________________________\n\n");
bool set_download_type = options[0].val, remove_console_data = options[1].val, remove_titlekey_crypto = options[2].val, change_acid_rsa = options[3].val;
bool set_download_type = options[0].val;
bool remove_console_data = options[1].val;
bool remove_titlekey_crypto = options[2].val;
bool change_acid_rsa = options[3].val;
bool patch_sua = options[4].val;
bool patch_screenshot = options[5].val;
bool patch_video_capture = options[6].val;
u8 *buf = NULL;
char *dump_name = NULL, *path = NULL;
@ -262,7 +271,11 @@ static void nspDump(TitleInfo *title_info)
goto end;
}
// add nacp mods here
if (!nacpGenerateNcaPatch(cur_nacp_ctx, patch_sua, patch_screenshot, patch_video_capture))
{
consolePrint("nacp nca patch failed (%s)\n", cur_nca_ctx->content_id_str);
goto end;
}
if (!nacpGenerateAuthoringToolXml(cur_nacp_ctx, title_info->version.value, cnmtGetRequiredTitleVersion(&cnmt_ctx)))
{
@ -523,18 +536,13 @@ static void nspDump(TitleInfo *title_info)
switch(cur_nca_ctx->content_type)
{
case NcmContentType_Meta:
{
cnmtWriteNcaPatch(&cnmt_ctx, buf, blksize, offset);
break;
}
case NcmContentType_Program:
{
ProgramInfoContext *cur_program_info_ctx = (ProgramInfoContext*)cur_nca_ctx->content_type_ctx;
programInfoWriteNcaPatch(cur_program_info_ctx, buf, blksize, offset);
programInfoWriteNcaPatch((ProgramInfoContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;
}
case NcmContentType_Control:
// write nacp patches here
nacpWriteNcaPatch((NacpContext*)cur_nca_ctx->content_type_ctx, buf, blksize, offset);
break;
default:
break;

View file

@ -320,14 +320,14 @@ void cnmtWriteNcaPatch(ContentMetaContext *cnmt_ctx, void *buf, u64 buf_size, u6
/* Using cnmtIsValidContext() here would probably take up precious CPU cycles. */
if (!cnmt_ctx || !cnmt_ctx->nca_ctx || cnmt_ctx->nca_ctx->content_type != NcmContentType_Meta || !cnmt_ctx->nca_ctx->content_type_ctx_patch || cnmt_ctx->nca_patch.written) return;
/* Attempt to write Partition FS entry. */
/* Attempt to write Partition FS entry patch. */
pfsWriteEntryPatchToMemoryBuffer(&(cnmt_ctx->pfs_ctx), &(cnmt_ctx->nca_patch), buf, buf_size, buf_offset);
/* Check if we need to update the NCA content type context patch status. */
if (cnmt_ctx->nca_patch.written)
{
cnmt_ctx->nca_ctx->content_type_ctx_patch = false;
LOGFILE("CNMT Partition FS file entry patch successfully written to NCA \"%s\"!", cnmt_ctx->nca_ctx->content_id_str);
LOGFILE("CNMT Partition FS entry patch successfully written to NCA \"%s\"!", cnmt_ctx->nca_ctx->content_id_str);
}
}

View file

@ -247,7 +247,7 @@ bool cnmtUpdateContentInfo(ContentMetaContext *cnmt_ctx, NcaContext *nca_ctx);
/// Generates a Partition FS entry patch for the NcaContext pointed to by the input ContentMetaContext, using its raw CNMT data.
bool cnmtGenerateNcaPatch(ContentMetaContext *cnmt_ctx);
/// Writes data from the Partition FS patch in the input ContentMetaContext to the provided buffer.
/// Writes data from the Partition FS entry patch in the input ContentMetaContext to the provided buffer.
void cnmtWriteNcaPatch(ContentMetaContext *cnmt_ctx, void *buf, u64 buf_size, u64 buf_offset);
/// Generates an AuthoringTool-like XML using information from a previously initialized ContentMetaContext, as well as a pointer to 'nca_ctx_count' NcaContext with content information.

View file

@ -329,6 +329,71 @@ end:
return success;
}
bool nacpGenerateNcaPatch(NacpContext *nacp_ctx, bool patch_sua, bool patch_screenshot, bool patch_video_capture)
{
if (!nacpIsValidContext(nacp_ctx))
{
LOGFILE("Invalid parameters!");
return false;
}
_NacpStruct *data = nacp_ctx->data;
u8 nacp_hash[SHA256_HASH_SIZE] = {0};
/* Check if we're not patching anything. */
if (!patch_sua && !patch_screenshot && !patch_video_capture) return true;
/* Patch StartupUserAccount, StartupUserAccountOption and UserAccountSwitchLock. */
if (patch_sua)
{
data->startup_user_account = NacpStartupUserAccount_None;
data->startup_user_account_option &= ~NacpStartupUserAccountOption_IsOptional;
data->user_account_switch_lock = NacpUserAccountSwitchLock_Disable;
}
/* Patch Screenshot. */
if (patch_screenshot) data->screenshot = NacpScreenshot_Allow;
/* Patch VideoCapture. */
if (patch_video_capture) data->video_capture = NacpVideoCapture_Enable;
/* Check if we really need to generate this patch. */
sha256CalculateHash(nacp_hash, data, sizeof(_NacpStruct));
if (!memcmp(nacp_hash, nacp_ctx->data_hash, sizeof(nacp_hash)))
{
LOGFILE("Skipping NACP patching - no flags have changed.");
return true;
}
/* Generate RomFS file entry patch. */
if (!romfsGenerateFileEntryPatch(&(nacp_ctx->romfs_ctx), nacp_ctx->romfs_file_entry, data, sizeof(_NacpStruct), 0, &(nacp_ctx->nca_patch)))
{
LOGFILE("Failed to generate RomFS file entry patch!");
return false;
}
/* Update NCA content type context patch status. */
nacp_ctx->nca_ctx->content_type_ctx_patch = true;
return true;
}
void nacpWriteNcaPatch(NacpContext *nacp_ctx, void *buf, u64 buf_size, u64 buf_offset)
{
/* Using nacpIsValidContext() here would probably take up precious CPU cycles. */
if (!nacp_ctx || !nacp_ctx->nca_ctx || nacp_ctx->nca_ctx->content_type != NcmContentType_Control || !nacp_ctx->nca_ctx->content_type_ctx_patch || nacp_ctx->nca_patch.written) return;
/* Attempt to write RomFS file entry patch. */
romfsWriteFileEntryPatchToMemoryBuffer(&(nacp_ctx->romfs_ctx), &(nacp_ctx->nca_patch), buf, buf_size, buf_offset);
/* Check if we need to update the NCA content type context patch status. */
if (nacp_ctx->nca_patch.written)
{
nacp_ctx->nca_ctx->content_type_ctx_patch = false;
LOGFILE("NACP RomFS file entry patch successfully written to NCA \"%s\"!", nacp_ctx->nca_ctx->content_id_str);
}
}
bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 required_system_version)
{
if (!nacpIsValidContext(nacp_ctx))
@ -424,13 +489,13 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
/* Rating. */
for(i = 0, count = 0; i < NacpRatingAgeOrganization_Count; i++)
{
u8 age = *((u8*)&(nacp->rating_age) + i);
if (age == 0xFF) continue;
s8 age = *(((s8*)&(nacp->rating_age)) + i);
if (age < 0) continue;
if (!utilsAppendFormattedStringToBuffer(&xml_buf, &xml_buf_size, \
" <Rating>\n" \
" <Organization>%s</Organization>\n" \
" <Age>%u</Age>\n" \
" <Age>%d</Age>\n" \
" </Rating>\n", \
nacpGetRatingAgeOrganizationString(i),
age)) goto end;
@ -450,19 +515,19 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "SaveDataOwnerId", nacp->save_data_owner_id)) goto end;
/* UserAccountSaveDataSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataSize", nacp->user_account_save_data_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataSize", (u64)nacp->user_account_save_data_size)) goto end;
/* UserAccountSaveDataJournalSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataJournalSize", nacp->user_account_save_data_journal_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataJournalSize", (u64)nacp->user_account_save_data_journal_size)) goto end;
/* DeviceSaveDataSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataSize", nacp->device_save_data_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataSize", (u64)nacp->device_save_data_size)) goto end;
/* DeviceSaveDataJournalSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataJournalSize", nacp->device_save_data_journal_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataJournalSize", (u64)nacp->device_save_data_journal_size)) goto end;
/* BcatDeliveryCacheStorageSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BcatDeliveryCacheStorageSize", nacp->bcat_delivery_cache_storage_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "BcatDeliveryCacheStorageSize", (u64)nacp->bcat_delivery_cache_storage_size)) goto end;
/* ApplicationErrorCodeCategory. */
if (!nacpAddStringFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "ApplicationErrorCodeCategory", nacp->application_error_code_category)) goto end;
@ -541,28 +606,28 @@ bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 requir
if (!nacpAddEnumFieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "AddOnContentRegistrationType", nacp->add_on_content_registration_type, &nacpGetAddOnContentRegistrationTypeString)) goto end;
/* UserAccountSaveDataSizeMax. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataSizeMax", nacp->user_account_save_data_size_max)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataSizeMax", (u64)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;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "UserAccountSaveDataJournalSizeMax", (u64)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;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataSizeMax", (u64)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;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "DeviceSaveDataJournalSizeMax", (u64)nacp->device_save_data_journal_size_max)) goto end;
/* TemporaryStorageSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "TemporaryStorageSize", nacp->temporary_storage_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "TemporaryStorageSize", (u64)nacp->temporary_storage_size)) goto end;
/* CacheStorageSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageSize", nacp->cache_storage_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageSize", (u64)nacp->cache_storage_size)) goto end;
/* CacheStorageJournalSize. */
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageJournalSize", nacp->cache_storage_journal_size)) goto end;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageJournalSize", (u64)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;
if (!nacpAddU64FieldToAuthoringToolXml(&xml_buf, &xml_buf_size, "CacheStorageDataAndJournalSizeMax", (u64)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;

View file

@ -75,7 +75,11 @@ typedef enum {
NacpLanguage_TraditionalChinese = 13,
NacpLanguage_SimplifiedChinese = 14,
NacpLanguage_BrazilianPortuguese = 15,
NacpLanguage_Count = 16 ///< Total values supported by this enum.
NacpLanguage_Count = 16, ///< Total values supported by this enum.
/// Old.
NacpLanguage_Taiwanese = NacpLanguage_TraditionalChinese,
NacpLanguage_Chinese = NacpLanguage_SimplifiedChinese
} NacpLanguage;
typedef enum {
@ -156,20 +160,20 @@ typedef enum {
} NacpRatingAgeOrganization;
typedef struct {
u8 cero;
u8 gracgcrb;
u8 gsrmr;
u8 esrb;
u8 class_ind;
u8 usk;
u8 pegi;
u8 pegi_portugal;
u8 pegibbfc;
u8 russian;
u8 acb;
u8 oflc;
u8 iarc_generic;
u8 reserved[0x13];
s8 cero;
s8 grac_gcrb;
s8 gsrmr;
s8 esrb;
s8 class_ind;
s8 usk;
s8 pegi;
s8 pegi_portugal;
s8 pegi_bbfc;
s8 russian;
s8 acb;
s8 oflc;
s8 iarc_generic;
s8 reserved[0x13];
} NacpRatingAge;
typedef enum {
@ -293,11 +297,11 @@ typedef struct {
char display_version[0x10];
u64 add_on_content_base_id;
u64 save_data_owner_id;
u64 user_account_save_data_size;
u64 user_account_save_data_journal_size;
u64 device_save_data_size;
u64 device_save_data_journal_size;
u64 bcat_delivery_cache_storage_size;
s64 user_account_save_data_size;
s64 user_account_save_data_journal_size;
s64 device_save_data_size;
s64 device_save_data_journal_size;
s64 bcat_delivery_cache_storage_size;
char application_error_code_category[0x8];
u64 local_communication_id[8];
u8 logo_type; ///< NacpLogoType.
@ -311,14 +315,14 @@ typedef struct {
char bcat_passphrase[0x41];
u8 startup_user_account_option; ///< NacpStartupUserAccountOption.
u8 reserved_2[0x6];
u64 user_account_save_data_size_max;
u64 user_account_save_data_journal_size_max;
u64 device_save_data_size_max;
u64 device_save_data_journal_size_max;
u64 temporary_storage_size;
u64 cache_storage_size;
u64 cache_storage_journal_size;
u64 cache_storage_data_and_journal_size_max;
s64 user_account_save_data_size_max;
s64 user_account_save_data_journal_size_max;
s64 device_save_data_size_max;
s64 device_save_data_journal_size_max;
s64 temporary_storage_size;
s64 cache_storage_size;
s64 cache_storage_journal_size;
s64 cache_storage_data_and_journal_size_max;
u16 cache_storage_index_max;
u8 reserved_3[0x6];
u64 play_log_queryable_application_id[0x10];
@ -363,6 +367,15 @@ typedef struct {
/// Initializes a NacpContext using a previously initialized NcaContext (which must belong to a Control NCA).
bool nacpInitializeContext(NacpContext *out, NcaContext *nca_ctx);
/// Changes flags in the NACP from the input NacpContext and generates a RomFS file entry patch if needed.
/// If 'patch_sua' is true, StartupUserAccount is set to None, the IsOptional bit in StartupUserAccountOption is cleared and UserAccountSwitchLock is set to Disable.
/// If 'patch_screenshot' is true, Screenshot is set to Allow.
/// If 'patch_video_capture' is true, VideoCapture is set to Enable.
bool nacpGenerateNcaPatch(NacpContext *nacp_ctx, bool patch_sua, bool patch_screenshot, bool patch_video_capture);
/// Writes data from the RomFS file entry patch in the input NacpContext to the provided buffer.
void nacpWriteNcaPatch(NacpContext *nacp_ctx, void *buf, u64 buf_size, u64 buf_offset);
/// Generates an AuthoringTool-like XML using information from a previously initialized NacpContext, as well as the Application/Patch version and the required system version.
/// If the function succeeds, XML data and size will get saved to the 'authoring_tool_xml' and 'authoring_tool_xml_size' members from the NacpContext.
bool nacpGenerateAuthoringToolXml(NacpContext *nacp_ctx, u32 version, u32 required_system_version);
@ -438,17 +451,4 @@ NX_INLINE bool nacpIsValidContext(NacpContext *nacp_ctx)
return true;
}
NX_INLINE bool nacpIsNcaPatchRequired(NacpContext *nacp_ctx)
{
if (!nacpIsValidContext(nacp_ctx)) return false;
u8 tmp_hash[SHA256_HASH_SIZE] = {0};
sha256CalculateHash(tmp_hash, nacp_ctx->data, sizeof(_NacpStruct));
return (memcmp(tmp_hash, nacp_ctx->data_hash, SHA256_HASH_SIZE) != 0);
}
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)));
}
#endif /* __NACP_H__ */

View file

@ -306,13 +306,13 @@ void npdmWriteNcaPatch(NpdmContext *npdm_ctx, void *buf, u64 buf_size, u64 buf_o
if (!npdm_ctx || !npdm_ctx->pfs_ctx || !npdm_ctx->pfs_ctx->nca_fs_ctx || !(nca_ctx = (NcaContext*)npdm_ctx->pfs_ctx->nca_fs_ctx->nca_ctx) || nca_ctx->content_type != NcmContentType_Program || \
!nca_ctx->content_type_ctx_patch || npdm_ctx->nca_patch.written) return;
/* Attempt to write Partition FS entry. */
/* Attempt to write Partition FS entry patch. */
pfsWriteEntryPatchToMemoryBuffer(npdm_ctx->pfs_ctx, &(npdm_ctx->nca_patch), buf, buf_size, buf_offset);
/* Check if we need to update the NCA content type context patch status. */
if (npdm_ctx->nca_patch.written)
{
nca_ctx->content_type_ctx_patch = false;
LOGFILE("NPDM Partition FS file entry patch successfully written to NCA \"%s\"!", nca_ctx->content_id_str);
LOGFILE("NPDM Partition FS entry patch successfully written to NCA \"%s\"!", nca_ctx->content_id_str);
}
}

View file

@ -557,7 +557,7 @@ bool npdmInitializeContext(NpdmContext *out, PartitionFileSystemContext *pfs_ctx
/// Changes the ACID public key from the NPDM in the input NpdmContext, updates the ACID signature from the NCA header in the underlying NCA context and generates a Partition FS entry patch.
bool npdmGenerateNcaPatch(NpdmContext *npdm_ctx);
/// Writes data from the Partition FS patch in the input NpdmContext to the provided buffer.
/// Writes data from the Partition FS entry patch in the input NpdmContext to the provided buffer.
void npdmWriteNcaPatch(NpdmContext *npdm_ctx, void *buf, u64 buf_size, u64 buf_offset);
/// Helper inline functions.

View file

@ -524,6 +524,8 @@ bool romfsGenerateFileEntryPatch(RomFileSystemContext *ctx, RomFileSystemFileEnt
success = ncaGenerateHierarchicalIntegrityPatch(ctx->nca_fs_ctx, data, data_size, fs_offset, &(out->cur_format_patch));
}
out->written = false;
if (!success) LOGFILE("Failed to generate 0x%lX bytes Hierarchical%s patch at offset 0x%lX for RomFS file entry!", data_size, \
ctx->nca_fs_ctx->section_type == NcaFsSectionType_Nca0RomFs ? "Sha256" : "Integrity", fs_offset);

View file

@ -106,6 +106,7 @@ typedef struct {
typedef struct {
bool use_old_format_patch; ///< Old format patch flag.
bool written; ///< Set to true if the patch has been completely written.
NcaHierarchicalSha256Patch old_format_patch; ///< Used with NCA0 RomFS sections.
NcaHierarchicalIntegrityPatch cur_format_patch; ///< Used with NCA2/NCA3 RomFS sections.
} RomFileSystemFileEntryPatch;
@ -183,17 +184,19 @@ NX_INLINE void romfsWriteFileEntryPatchToMemoryBuffer(RomFileSystemContext *ctx,
if (patch->use_old_format_patch)
{
ncaWriteHierarchicalSha256PatchToMemoryBuffer((NcaContext*)ctx->nca_fs_ctx->nca_ctx, &(patch->old_format_patch), buf, buf_size, buf_offset);
patch->written = patch->old_format_patch.written;
} else {
ncaWriteHierarchicalIntegrityPatchToMemoryBuffer((NcaContext*)ctx->nca_fs_ctx->nca_ctx, &(patch->cur_format_patch), buf, buf_size, buf_offset);
patch->written = patch->cur_format_patch.written;
}
}
NX_INLINE void romfsFreeFileEntryPatch(RomFileSystemFileEntryPatch *patch)
{
if (!patch) return;
patch->use_old_format_patch = false;
ncaFreeHierarchicalSha256Patch(&(patch->old_format_patch));
ncaFreeHierarchicalIntegrityPatch(&(patch->cur_format_patch));
memset(patch, 0, sizeof(RomFileSystemFileEntryPatch));
}
#endif /* __ROMFS_H__ */

View file

@ -7,31 +7,28 @@ list of top level functions designed to alter nca data in order of (possible) us
* ncaRemoveTitlekeyCrypto (can be used with digital titles + game updates in gamecards)
* cnmtGenerateNcaPatch (Meta)
* calls pfsGenerateEntryPatch
* calls ncaGenerateHierarchicalSha256Patch
* programInfoGenerateNcaPatch (Program)
* calls npdmChangeAcidPublicKeyAndNcaSignature
* calls npdmGenerateNcaPatch
* calls pfsGenerateEntryPatch
* calls ncaGenerateHierarchicalSha256Patch
* nacpGenerateNcaPatch (Control)
* calls romfsGenerateFileEntryPatch
* calls ncaGenerateHierarchicalSha256Patch / ncaGenerateHierarchicalIntegrityPatch
* nacpIsNcaPatchRequired is used to check if a nacp patch was applied
* missing wrapper for romfsWriteFileEntryPatchToMemoryBuffer !!!
* missing functions for nacp mods !!!
* ncaEncryptHeader (doesn't modify anything per se, but it's used to generate new encrypted header data if needed)
inside dump loop:
* cnmtGenerateNcaPatch (Meta)
* calls pfsGenerateEntryPatch
* calls ncaGenerateHierarchicalSha256Patch
* returns true if cnmt needs no patching
* demands an immediate ncaEncryptHeader call
* ncaIsHeaderDirty (doesn't modify anything per se, but it's used to check if any of the functions above has been used, basically - and by extension, if the functions below need to be used)
* ncaWriteEncryptedHeaderDataToMemoryBuffer (write encrypted nca header data)
* cnmtUpdateContentInfo (used to update content entry info in the raw cnmt copy after dumping each one)
* cnmtWriteNcaPatch (writes cnmt patch)
* calls pfsWriteEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer
@ -41,16 +38,16 @@ list of top level functions designed to alter nca data in order of (possible) us
* calls pfsWriteEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer
* pfsWriteEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer
* nacpWriteNcaPatch (writes nacp patch)
* calls romfsWriteFileEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer / ncaWriteHierarchicalIntegrityPatchToMemoryBuffer
* romfsWriteFileEntryPatchToMemoryBuffer
* calls ncaWriteHierarchicalSha256PatchToMemoryBuffer / ncaWriteHierarchicalIntegrityPatchToMemoryBuffer
* missing nacp wrapper
* cnmtUpdateContentInfo (used to update content entry info in the raw cnmt copy after dumping each one - ignores the current content if its a meta nca)
minor steps to take into account:
* check if rights_id_available == true and titlekey_retrieved == false (preload handling)
* actually, just inform the user about it - this is being handled