Changes

2,504 bytes added ,  19:28, 18 October 2022
Fix new field name
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 9 different filenames used for ".cnmt":
  −
* "Application_{lower-case hex titleID}.cnmt"
  −
* "Patch_{lower-case hex titleID}.cnmt"
  −
* "AddOnContent_{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"
  −
* "Delta_{lower-case hex titleID}.cnmt"
  −
  −
It starts with a header:
   
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 25: 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 [[NCM_services#Title_Types|Title Types]])
+
| [[NCM_services#ContentMetaType|ContentMetaType]]
 
|-
 
|-
 
| 0xD
 
| 0xD
| 1
+
| 0x1
|
+
| 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 72: 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 88: 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 104: 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 124: 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=[[Internet_Browser|HtmlDocument]], 5=[[Internet_Browser|LegalInformation]], 6=[[NCA_Format|DeltaFragment]])
+
| 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 155: Line 247:  
|-
 
|-
 
| 0x0
 
| 0x0
| 8
+
| 0x8
| Title ID
+
| Id
 
|-
 
|-
 
| 0x8
 
| 0x8
| 4
+
| 0x4
| Title version
+
| Version
 
|-
 
|-
 
| 0xC
 
| 0xC
| 1
+
| 0x1
| Type (see [[NCM_services#Title_Types|Title Types]])
+
| [[NCM_services#Title_Types|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 188: 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 264: 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 [[NCM_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 310: 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 348: 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 386: 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 [[NCM_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 436: 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 [[NCM_services#Title_Types|Title Types]])
+
| Reserved
 
|-
 
|-
| 0x17
+
| 0x20
| 1
+
| 0x34 * FragmentSetCount
|  
+
| [[#FragmentSet|FragmentSet]]
 
|-
 
|-
 +
| Variable
 +
| 0x4 * FragmentIndicatorCount (from [[#FragmentSet|FragmentSet]])
 +
| [[#FragmentIndicator|FragmentIndicator]]
 
|}
 
|}
   −
This contains information on previous title content from earlier patches.
+
= Digest =
 +
Always found at the end of the file.
 +
 
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 0x20
 +
| Digest
 +
|}