Difference between revisions of "CNMT"

(Add info on extra data for patches)
 
(28 intermediate revisions by 7 users not shown)
Line 1: Line 1:
For the content of the NCA FS which can be [[Filesystem_services|mounted]], see [[NCA_Content_FS|here]].
+
This is the metadata file that ends in <code>".cnmt{.nca}"</code> or <code>"meta0.ncd"</code>. This seems to replace the TMD format.
  
For the format of the actual NCA, see [[NCA_Format|here]].
+
The official name for CNMT is "PackagedContentMeta".
  
= Metadata file =
+
= PackagedContentMetaHeader =
This is the file that ends in <code>".cnmt{.nca}"</code> or <code>"meta0.ncd"</code>. This seems to replace the TMD format.
+
This is "nn::ncm::PackagedContentMetaHeader".
  
There's at least 7 different filenames used for ".cnmt":
 
* "Application_{lower-case hex titleID}.cnmt"
 
* "Patch_{lower-case hex titleID}.cnmt"
 
* "SystemUpdate_{hex titleID}.cnmt"
 
* "SystemData_{lower-case hex titleID}.cnmt"
 
* "SystemProgram_{lower-case hex titleID}.cnmt"
 
* "BootImagePackage_{lower-case hex titleID}.cnmt"
 
* "BootImagePackageSafe_{lower-case hex titleID}.cnmt"
 
 
It starts with a header:
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 23: Line 13:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 8
+
| 0x8
| Title ID
+
| Id
 
|-
 
|-
 
| 0x8
 
| 0x8
| 4
+
| 0x4
| u32 [[Title_list|title-version]]
+
| Version
 
|-
 
|-
 
| 0xC
 
| 0xC
| 1
+
| 0x1
| Type (see [[Content_Manager_services#Title_Types|Title Types]])
+
| [[NCM_services#ContentMetaType|ContentMetaType]]
 
|-
 
|-
 
| 0xD
 
| 0xD
| 1
+
| 0x1
|
+
| [17.0.0+] [[NCM_services#ContentMetaPlatform|ContentMetaPlatform]] ([1.0.0-16.1.0] Reserved)
 
|-
 
|-
 
| 0xE
 
| 0xE
| 2
+
| 0x2
| Offset to table relative to the end of this 0x20-byte header.
+
| ExtendedHeaderSize
 
|-
 
|-
 
| 0x10
 
| 0x10
| 2
+
| 0x2
| Number of content entries
+
| ContentCount
 
|-
 
|-
 
| 0x12
 
| 0x12
| 2
+
| 0x2
| Number of meta entries
+
| ContentMetaCount
 
|-
 
|-
 
| 0x14
 
| 0x14
| 12
+
| 0x1
|
+
| ContentMetaAttributes (0=None, 1=IncludesExFatDriver, 2=Rebootless, 4=Compacted)
 +
|-
 +
| 0x15
 +
| 0x3
 +
| Reserved
 +
|-
 +
| 0x18
 +
| 0x4
 +
| RequiredDownloadSystemVersion
 +
|-
 +
| 0x1C
 +
| 0x4
 +
| Reserved
 
|}
 
|}
  
With SystemUpdate, the 4-bytes at offset 0xE are zero, with the entry-count field located at offset 0x12 instead(header size is the same).
+
= SystemUpdateMetaExtendedHeader =
 +
This is "nn::ncm::SystemUpdateMetaExtendedHeader".
  
An optional header can follow, depending on the title type.
+
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x4
 +
| ExtendedDataSize
 +
|}
 +
 
 +
= ApplicationMetaExtendedHeader =
 +
This is "nn::ncm::ApplicationMetaExtendedHeader".
  
At the end of the file following the entries is a 0x20-byte block, presumably a hash.
+
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x8
 +
| PatchId
 +
|-
 +
| 0x8
 +
| 0x4
 +
| RequiredSystemVersion
 +
|-
 +
| 0xC
 +
| 0x4
 +
| RequiredApplicationVersion
 +
|}
  
With Patch-format, there's additional data after the end of the entries specified in the header and before the ending hash.
+
= PatchMetaExtendedHeader =
 +
This is "nn::ncm::PatchMetaExtendedHeader".
  
== Application header ==
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 70: Line 102:
 
! Description
 
! Description
 
|-
 
|-
| 0x20
+
| 0x0
| 8
+
| 0x8
| Patch Title ID
+
| ApplicationId
 +
|-
 +
| 0x8
 +
| 0x4
 +
| RequiredSystemVersion
 +
|-
 +
| 0xC
 +
| 0x4
 +
| ExtendedDataSize
 
|-
 
|-
| 0x28
+
| 0x10
| 8
+
| 0x8
| Minimum system version
+
| Reserved
 
|}
 
|}
  
== Patch header ==
+
= AddOnContentMetaExtendedHeader =
 +
This is "nn::ncm::AddOnContentMetaExtendedHeader".
 +
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 86: Line 128:
 
! Description
 
! Description
 
|-
 
|-
| 0x20
+
| 0x0
| 8
+
| 0x8
| Original title ID
+
| ApplicationId
 +
|-
 +
| 0x8
 +
| 0x4
 +
| RequiredApplicationVersion
 +
|-
 +
| 0xC
 +
| 0x1
 +
| [15.0.0+] ContentAccessibilities ([1.0.0-14.1.2] Reserved)
 +
|-
 +
| 0xD
 +
| 0x3
 +
| Reserved
 
|-
 
|-
| 0x28
+
| 0x10
| 8
+
| 0x8
| Minimum system version
+
| [15.0.0+] DataPatchId
 
|}
 
|}
  
== Add-on content header ==
+
= DeltaMetaExtendedHeader =
 +
This is "nn::ncm::DeltaMetaExtendedHeader".
 +
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 102: Line 158:
 
! Description
 
! Description
 
|-
 
|-
| 0x20
+
| 0x0
| 8
+
| 0x8
| Application title ID
+
| ApplicationId
 +
|-
 +
| 0x8
 +
| 0x4
 +
| ExtendedDataSize
 
|-
 
|-
| 0x28
+
| 0xC
| 8
+
| 0x4
| Minimum application version
+
| Reserved
 
|}
 
|}
  
== Content records ==
+
= DataPatchMetaExtendedHeader =
 +
This is "nn::ncm::DataPatchMetaExtendedHeader".
  
Each entry is 0x38 bytes:
+
This was added with [15.0.0+].
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 122: Line 183:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 32
+
| 0x8
| Hash
+
| DataId
 +
|-
 +
| 0x8
 +
| 0x8
 +
| ApplicationId
 +
|-
 +
| 0x10
 +
| 0x4
 +
| RequiredApplicationVersion
 +
|-
 +
| 0x14
 +
| 0x4
 +
| ExtendedDataSize
 +
|-
 +
| 0x18
 +
| 0x8
 +
| Reserved
 +
|}
 +
 
 +
= PackagedContentInfo =
 +
This is "nn::ncm::PackagedContentInfo".
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x20
 +
| Hash (SHA256 of the referenced content)
 
|-
 
|-
 
| 0x20
 
| 0x20
| 16
+
| 0x10
| NcaId [same as first 16-bytes of hash]
+
| ContentId
 
|-
 
|-
 
| 0x30
 
| 0x30
| 6
+
| [15.0.0+] 0x5 ([1.0.0-14.1.2] 0x6)
| Size, same as the output from [[Content_Manager_services#GetEntrySize]].
+
| Size
 +
|-
 +
| 0x35
 +
| 0x1
 +
| [15.0.0+] ContentAttributes
 
|-
 
|-
 
| 0x36
 
| 0x36
| 1
+
| 0x1
| Type (0=meta, 1=program, 2=data, 3=control, 4=offline-manual [[Internet_Browser|html]], 5=legal [[Internet_Browser|html]], 6=[[NCA_Format|game-update]] RomFS patches?)
+
| ContentType (0=Meta, 1=Program, 2=Data, 3=Control, 4=[[Internet_Browser|HtmlDocument]], 5=[[Internet_Browser|LegalInformation]], 6=[[NCA_Format|DeltaFragment]])
 
|-
 
|-
 
| 0x37
 
| 0x37
| 1
+
| 0x1
|
+
| IdOffset
 
|}
 
|}
  
== Meta records ==
+
= ContentMetaInfo =
 
+
This is "nn::ncm::ContentMetaInfo".
Each entry is 0x10 bytes:
 
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 153: Line 247:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 8
+
| 0x8
| Title ID
+
| Id
 
|-
 
|-
 
| 0x8
 
| 0x8
| 4
+
| 0x4
| Title version
+
| Version
 
|-
 
|-
 
| 0xC
 
| 0xC
| 1
+
| 0x1
| Type (see [[Content_Manager_services#Title_Types|Title Types]])
+
| [[NCM_services#ContentMetaType|ContentMetaType]]
 
|-
 
|-
 
| 0xD
 
| 0xD
| 1
+
| 0x1
| ? bit0 set = don't install?
+
| ContentMetaAttributes (0=None, 1=IncludesExFatDriver, 2=Rebootless, 4=Compacted)
 
|-
 
|-
 
| 0xE
 
| 0xE
| 2
+
| 0x2
| Unused?
+
| Reserved
 
|}
 
|}
  
This is used for SystemUpdate, see here: [[Content_Manager_services#GetUpdateTitleList]].
+
This is used for SystemUpdate, see here: [[NCM_services#ReadEntryMetaRecords]].
  
== Extended data ==
+
= SystemUpdateMetaExtendedData =
 
+
This is "nn::ncm::SystemUpdateMetaExtendedData".
Patch-type cnmt files include an extended data section.  
 
  
 +
If the Version field is 1, the format is:
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 186: Line 280:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 4
+
| 0x4
| Number of previous cnmt entries.
+
| Version
 
|-
 
|-
 
| 0x4
 
| 0x4
| 4
+
| 0x4
| Number of previous delta entries.
+
| VariationCount
 
|-
 
|-
 
| 0x8
 
| 0x8
| 4
+
| 0x20 * VariationCount
| Number of delta info entries.
+
| [[#FirmwareVariationInfo|FirmwareVariationInfo]] (Version 1)
 +
|}
 +
 
 +
If the Version field is 2, the format is:
 +
{| class="wikitable" border="1"
 
|-
 
|-
| 0xC
+
! Offset
| 4
+
! Size
| Number of delta application info entries.
+
! Description
 
|-
 
|-
| 0x10
+
| 0x0
| 4
+
| 0x4
| Number of previous content entries.
+
| Version
 
|-
 
|-
| 0x14
+
| 0x4
| 4
+
| 0x4
| Number of delta content entries.
+
| VariationCount
 
|-
 
|-
| 0x18
+
| 0x8
| 4
+
| 0x4 * VariationCount
| Unused?
+
| FirmwareVariationId
 
|-
 
|-
| 0x1C
+
| Variable
| 0x38*X
+
| 0x20 * VariationCount
| Previous cnmt entries
+
| [[#FirmwareVariationInfo|FirmwareVariationInfo]] (Version 2)
 
|-
 
|-
|  
+
| Variable
| 0x28*X
+
| 0x10 * MetaCount (from [[#FirmwareVariationInfo|FirmwareVariationInfo]] (Version 2))
| Previous delta entries
+
| [[#ContentMetaInfo|ContentMetaInfo]] (if ReferToBase is False)
 +
|}
 +
 
 +
== FirmwareVariationInfo ==
 +
This is "FirmwareVariationInfo ".
 +
 
 +
If the Version field is 1, the format is:
 +
{| class="wikitable" border="1"
 
|-
 
|-
|
+
! Offset
| 0x28*X
+
! Size
| Delta info entries
+
! Description
 
|-
 
|-
|  
+
| 0x0
| 0x34*X
+
| 0x4
| Delta application info entries
+
| FirmwareVariationId
 
|-
 
|-
|  
+
| 0x4
| 0x18*X
+
| 0x1C
| Previous content entries
+
| Reserved
 +
|}
 +
 
 +
If the Version field is 2, the format is:
 +
{| class="wikitable" border="1"
 
|-
 
|-
|
+
! Offset
| 0x38*X
+
! Size
| Delta content entries. (Standard content records)
+
! Description
 
|-
 
|-
|  
+
| 0x0
| 4
+
| 0x1
| Unknown
+
| ReferToBase (0=False, 1=True)
 
|-
 
|-
|  
+
| 0x1
| 4
+
| 0x3
| Unknown
+
| Reserved
 
|-
 
|-
|  
+
| 0x4
| 4
+
| 0x4
| Unknown
+
| MetaCount
 
|-
 
|-
 +
| 0x8
 +
| 0x18
 +
| Reserved
 
|}
 
|}
  
== Previous cnmt records ==
+
= PatchMetaExtendedData =
 
+
This is "nn::ncm::PatchMetaExtendedData".
Each entry is 0x38 bytes:
 
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 262: Line 373:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 8
+
| 0x4
| Title ID
+
| PatchHistoryHeaderCount
 +
|-
 +
| 0x4
 +
| 0x4
 +
| PatchDeltaHistoryCount
 
|-
 
|-
 
| 0x8
 
| 0x8
| 4
+
| 0x4
| Title version
+
| PatchDeltaHeaderCount
 
|-
 
|-
 
| 0xC
 
| 0xC
| 1
+
| 0x4
| Type (see [[Content_Manager_services#Title_Types|Title Types]])
+
| FragmentSetCount
 +
|-
 +
| 0x10
 +
| 0x4
 +
| PatchHistoryContentInfoCount
 +
|-
 +
| 0x14
 +
| 0x4
 +
| PatchDeltaPackagedContentInfoCount
 
|-
 
|-
| 0xD
+
| 0x18
| 3
+
| 0x4
| Unused?
+
| Reserved
 +
|-
 +
| 0x1C
 +
| 0x38 * PatchHistoryHeaderCount
 +
| [[#PatchHistoryHeader|PatchHistoryHeader]]
 +
|-
 +
| Variable
 +
| 0x28 * PatchDeltaHistoryCount
 +
| [[#PatchDeltaHistory|PatchDeltaHistory]]
 
|-
 
|-
| 0x10
+
| Variable
| 32
+
| 0x28 * PatchDeltaHeaderCount
| Hash
+
| [[#PatchDeltaHeader|PatchDeltaHeader]]
 
|-
 
|-
| 0x30
+
| Variable
| 2
+
| 0x34 * FragmentSetCount
| Unknown
+
| [[#FragmentSet|FragmentSet]]
 
|-
 
|-
| 0x32
+
| Variable
| 2
+
| 0x18 * PatchHistoryContentInfoCount
| Unused?
+
| [[#PackagedContentInfo|PatchHistoryContentInfo]] ([[#PackagedContentInfo|PackagedContentInfo]] without the Hash entry)
 
|-
 
|-
| 0x34
+
| Variable
| 4
+
| 0x38 * PatchDeltaPackagedContentInfoCount
| Unused?
+
| [[#PackagedContentInfo|PatchDeltaPackagedContentInfo]]
 
|-
 
|-
 +
| Variable
 +
| 0x4 * FragmentIndicatorCount (from [[#FragmentSet|FragmentSet]])
 +
| [[#FragmentIndicator|FragmentIndicator]]
 
|}
 
|}
  
This contains information on previous metadata files.
+
== PatchHistoryHeader ==
 +
This is "nn::ncm::PatchHistoryHeader".
  
== Previous delta records ==
+
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x10
 +
| ContentMetaKey
 +
|-
 +
| 0x10
 +
| 0x20
 +
| Digest
 +
|-
 +
| 0x30
 +
| 0x2
 +
| ContentInfoCount
 +
|-
 +
| 0x32
 +
| 0x6
 +
| Reserved
 +
|}
  
Each entry is 0x28 bytes:
+
== PatchDeltaHistory ==
 +
This is "nn::ncm::PatchDeltaHistory".
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 308: Line 465:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 8
+
| 0x8
| Old title ID
+
| SourcePatchId
 
|-
 
|-
 
| 0x8
 
| 0x8
| 8
+
| 0x8
| New title ID
+
| DestinationPatchId
 
|-
 
|-
 
| 0x10
 
| 0x10
| 4
+
| 0x4
| Old title version
+
| SourceVersion
 
|-
 
|-
 
| 0x14
 
| 0x14
| 4
+
| 0x4
| New title version
+
| DestinationVersion
 
|-
 
|-
 
| 0x18
 
| 0x18
| 8
+
| 0x8
| Size
+
| DownloadSize
 
|-
 
|-
 
| 0x20
 
| 0x20
| 8
+
| 0x8
| Unused?
+
| Reserved
|-
 
 
|}
 
|}
  
This contains information on previous delta patches.
+
== PatchDeltaHeader ==
 
+
This is "nn::ncm::PatchDeltaHeader".
== Delta info records ==
 
 
 
Each entry is 0x28 bytes:
 
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 346: Line 499:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 8
+
| 0x8
| Old title ID
+
| SourcePatchId
 
|-
 
|-
 
| 0x8
 
| 0x8
 
| 8
 
| 8
| New title ID
+
| DestinationPatchId
 
|-
 
|-
 
| 0x10
 
| 0x10
| 4
+
| 0x4
| Old title version
+
| SourceVersion
 
|-
 
|-
 
| 0x14
 
| 0x14
| 4
+
| 0x4
| New title version
+
| DestinationVersion
 
|-
 
|-
 
| 0x18
 
| 0x18
| 8
+
| 0x2
| Some sort of index?
+
| FragmentSetCount
 +
|-
 +
| 0x1A
 +
| 0x6
 +
| Reserved
 
|-
 
|-
 
| 0x20
 
| 0x20
| 8
+
| 0x2
| Some sort of index?
+
| ContentInfoCount
 
|-
 
|-
 +
| 0x22
 +
| 0x6
 +
| Reserved
 
|}
 
|}
  
This contains information on the current delta patch.
+
== FragmentSet ==
 
+
This is "nn::ncm::FragmentSet".
== Delta application info records ==
 
 
 
Each entry is 0x34 bytes:
 
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 384: Line 541:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 16
+
| 0x10
| Old NcaId
+
| SourceContentId
 
|-
 
|-
 
| 0x10
 
| 0x10
| 16
+
| 0x10
| New NcaId
+
| DestinationContentId
 
|-
 
|-
 
| 0x20
 
| 0x20
| 6
+
| 0x6
| Old size
+
| SourceSize
 
|-
 
|-
 
| 0x26
 
| 0x26
| 2
+
| 0x6
| Upper 2 bytes of the new size
+
| DestinationSize
|-
 
| 0x28
 
| 4
 
| Lower 4 bytes of the new size
 
 
|-
 
|-
 
| 0x2C
 
| 0x2C
| 2
+
| 0x2
| Unknown
+
| FragmentIndicatorCount
 
|-
 
|-
 
| 0x2E
 
| 0x2E
| 1
+
| 0x1
| Type (see [[Content_Manager_services#Title_Types|Title Types]])
+
| FragmentTargetContentType (0=Meta, 1=Program, 2=Data, 3=Control, 4=[[Internet_Browser|HtmlDocument]], 5=[[Internet_Browser|LegalInformation]], 6=[[NCA_Format|DeltaFragment]])
 
|-
 
|-
 
| 0x2F
 
| 0x2F
| 1
+
| 0x1
| ? bit0 set = don't install?
+
| UpdateType (0=ApplyAsDelta, 1=Overwrite, 2=Create)
 
|-
 
|-
 
| 0x30
 
| 0x30
| 4
+
| 0x4
| Unused?
+
| Reserved
|-
 
 
|}
 
|}
  
This contains information on how to apply deltas to the previous patch.
+
== FragmentIndicator ==
 +
This is "nn::ncm::FragmentIndicator".
  
== Previous content records ==
+
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x2
 +
| ContentInfoIndex
 +
|-
 +
| 0x2
 +
| 0x2
 +
| FragmentIndex
 +
|}
  
Each entry is 0x18 bytes:
+
= DeltaMetaExtendedData =
 +
This is "nn::ncm::DeltaMetaExtendedData".
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 434: Line 601:
 
|-
 
|-
 
| 0x0
 
| 0x0
| 16
+
| 0x8
| NcaId
+
| SourcePatchId
 +
|-
 +
| 0x8
 +
| 0x8
 +
| DestinationPatchId
 
|-
 
|-
 
| 0x10
 
| 0x10
| 6
+
| 0x4
| Size
+
| SourceVersion
 +
|-
 +
| 0x14
 +
| 0x4
 +
| DestinationVersion
 +
|-
 +
| 0x18
 +
| 0x2
 +
| FragmentSetCount
 
|-
 
|-
| 0x16
+
| 0x1A
| 1
+
| 0x6
| Type (see [[Content_Manager_services#Title_Types|Title Types]])
+
| Reserved
 
|-
 
|-
| 0x17
+
| 0x20
| 1
+
| 0x34 * FragmentSetCount
|  
+
| [[#FragmentSet|FragmentSet]]
 
|-
 
|-
 +
| Variable
 +
| 0x4 * FragmentIndicatorCount (from [[#FragmentSet|FragmentSet]])
 +
| [[#FragmentIndicator|FragmentIndicator]]
 +
|}
 +
 +
= Digest =
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x20
 +
| Digest
 
|}
 
|}
  
This contains information on previous title content from earlier patches.
+
This is a SHA-256 hash always found at the end of the file. The hash is calculated over the CNMT file's contents, but this is only done for the development version of the file which results in its production version counterpart sharing the same hash value.

Latest revision as of 21:27, 15 October 2023

This is the metadata file that ends in ".cnmt{.nca}" or "meta0.ncd". This seems to replace the TMD format.

The official name for CNMT is "PackagedContentMeta".

PackagedContentMetaHeader

This is "nn::ncm::PackagedContentMetaHeader".

Offset Size Description
0x0 0x8 Id
0x8 0x4 Version
0xC 0x1 ContentMetaType
0xD 0x1 [17.0.0+] ContentMetaPlatform ([1.0.0-16.1.0] Reserved)
0xE 0x2 ExtendedHeaderSize
0x10 0x2 ContentCount
0x12 0x2 ContentMetaCount
0x14 0x1 ContentMetaAttributes (0=None, 1=IncludesExFatDriver, 2=Rebootless, 4=Compacted)
0x15 0x3 Reserved
0x18 0x4 RequiredDownloadSystemVersion
0x1C 0x4 Reserved

SystemUpdateMetaExtendedHeader

This is "nn::ncm::SystemUpdateMetaExtendedHeader".

Offset Size Description
0x0 0x4 ExtendedDataSize

ApplicationMetaExtendedHeader

This is "nn::ncm::ApplicationMetaExtendedHeader".

Offset Size Description
0x0 0x8 PatchId
0x8 0x4 RequiredSystemVersion
0xC 0x4 RequiredApplicationVersion

PatchMetaExtendedHeader

This is "nn::ncm::PatchMetaExtendedHeader".

Offset Size Description
0x0 0x8 ApplicationId
0x8 0x4 RequiredSystemVersion
0xC 0x4 ExtendedDataSize
0x10 0x8 Reserved

AddOnContentMetaExtendedHeader

This is "nn::ncm::AddOnContentMetaExtendedHeader".

Offset Size Description
0x0 0x8 ApplicationId
0x8 0x4 RequiredApplicationVersion
0xC 0x1 [15.0.0+] ContentAccessibilities ([1.0.0-14.1.2] Reserved)
0xD 0x3 Reserved
0x10 0x8 [15.0.0+] DataPatchId

DeltaMetaExtendedHeader

This is "nn::ncm::DeltaMetaExtendedHeader".

Offset Size Description
0x0 0x8 ApplicationId
0x8 0x4 ExtendedDataSize
0xC 0x4 Reserved

DataPatchMetaExtendedHeader

This is "nn::ncm::DataPatchMetaExtendedHeader".

This was added with [15.0.0+].

Offset Size Description
0x0 0x8 DataId
0x8 0x8 ApplicationId
0x10 0x4 RequiredApplicationVersion
0x14 0x4 ExtendedDataSize
0x18 0x8 Reserved

PackagedContentInfo

This is "nn::ncm::PackagedContentInfo".

Offset Size Description
0x0 0x20 Hash (SHA256 of the referenced content)
0x20 0x10 ContentId
0x30 [15.0.0+] 0x5 ([1.0.0-14.1.2] 0x6) Size
0x35 0x1 [15.0.0+] ContentAttributes
0x36 0x1 ContentType (0=Meta, 1=Program, 2=Data, 3=Control, 4=HtmlDocument, 5=LegalInformation, 6=DeltaFragment)
0x37 0x1 IdOffset

ContentMetaInfo

This is "nn::ncm::ContentMetaInfo".

Offset Size Description
0x0 0x8 Id
0x8 0x4 Version
0xC 0x1 ContentMetaType
0xD 0x1 ContentMetaAttributes (0=None, 1=IncludesExFatDriver, 2=Rebootless, 4=Compacted)
0xE 0x2 Reserved

This is used for SystemUpdate, see here: NCM_services#ReadEntryMetaRecords.

SystemUpdateMetaExtendedData

This is "nn::ncm::SystemUpdateMetaExtendedData".

If the Version field is 1, the format is:

Offset Size Description
0x0 0x4 Version
0x4 0x4 VariationCount
0x8 0x20 * VariationCount FirmwareVariationInfo (Version 1)

If the Version field is 2, the format is:

Offset Size Description
0x0 0x4 Version
0x4 0x4 VariationCount
0x8 0x4 * VariationCount FirmwareVariationId
Variable 0x20 * VariationCount FirmwareVariationInfo (Version 2)
Variable 0x10 * MetaCount (from FirmwareVariationInfo (Version 2)) ContentMetaInfo (if ReferToBase is False)

FirmwareVariationInfo

This is "FirmwareVariationInfo ".

If the Version field is 1, the format is:

Offset Size Description
0x0 0x4 FirmwareVariationId
0x4 0x1C Reserved

If the Version field is 2, the format is:

Offset Size Description
0x0 0x1 ReferToBase (0=False, 1=True)
0x1 0x3 Reserved
0x4 0x4 MetaCount
0x8 0x18 Reserved

PatchMetaExtendedData

This is "nn::ncm::PatchMetaExtendedData".

Offset Size Description
0x0 0x4 PatchHistoryHeaderCount
0x4 0x4 PatchDeltaHistoryCount
0x8 0x4 PatchDeltaHeaderCount
0xC 0x4 FragmentSetCount
0x10 0x4 PatchHistoryContentInfoCount
0x14 0x4 PatchDeltaPackagedContentInfoCount
0x18 0x4 Reserved
0x1C 0x38 * PatchHistoryHeaderCount PatchHistoryHeader
Variable 0x28 * PatchDeltaHistoryCount PatchDeltaHistory
Variable 0x28 * PatchDeltaHeaderCount PatchDeltaHeader
Variable 0x34 * FragmentSetCount FragmentSet
Variable 0x18 * PatchHistoryContentInfoCount PatchHistoryContentInfo (PackagedContentInfo without the Hash entry)
Variable 0x38 * PatchDeltaPackagedContentInfoCount PatchDeltaPackagedContentInfo
Variable 0x4 * FragmentIndicatorCount (from FragmentSet) FragmentIndicator

PatchHistoryHeader

This is "nn::ncm::PatchHistoryHeader".

Offset Size Description
0x0 0x10 ContentMetaKey
0x10 0x20 Digest
0x30 0x2 ContentInfoCount
0x32 0x6 Reserved

PatchDeltaHistory

This is "nn::ncm::PatchDeltaHistory".

Offset Size Description
0x0 0x8 SourcePatchId
0x8 0x8 DestinationPatchId
0x10 0x4 SourceVersion
0x14 0x4 DestinationVersion
0x18 0x8 DownloadSize
0x20 0x8 Reserved

PatchDeltaHeader

This is "nn::ncm::PatchDeltaHeader".

Offset Size Description
0x0 0x8 SourcePatchId
0x8 8 DestinationPatchId
0x10 0x4 SourceVersion
0x14 0x4 DestinationVersion
0x18 0x2 FragmentSetCount
0x1A 0x6 Reserved
0x20 0x2 ContentInfoCount
0x22 0x6 Reserved

FragmentSet

This is "nn::ncm::FragmentSet".

Offset Size Description
0x0 0x10 SourceContentId
0x10 0x10 DestinationContentId
0x20 0x6 SourceSize
0x26 0x6 DestinationSize
0x2C 0x2 FragmentIndicatorCount
0x2E 0x1 FragmentTargetContentType (0=Meta, 1=Program, 2=Data, 3=Control, 4=HtmlDocument, 5=LegalInformation, 6=DeltaFragment)
0x2F 0x1 UpdateType (0=ApplyAsDelta, 1=Overwrite, 2=Create)
0x30 0x4 Reserved

FragmentIndicator

This is "nn::ncm::FragmentIndicator".

Offset Size Description
0x0 0x2 ContentInfoIndex
0x2 0x2 FragmentIndex

DeltaMetaExtendedData

This is "nn::ncm::DeltaMetaExtendedData".

Offset Size Description
0x0 0x8 SourcePatchId
0x8 0x8 DestinationPatchId
0x10 0x4 SourceVersion
0x14 0x4 DestinationVersion
0x18 0x2 FragmentSetCount
0x1A 0x6 Reserved
0x20 0x34 * FragmentSetCount FragmentSet
Variable 0x4 * FragmentIndicatorCount (from FragmentSet) FragmentIndicator

Digest

Offset Size Description
0x0 0x20 Digest

This is a SHA-256 hash always found at the end of the file. The hash is calculated over the CNMT file's contents, but this is only done for the development version of the file which results in its production version counterpart sharing the same hash value.