Changes

2,812 bytes added ,  21:27, 15 October 2023
no edit summary
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
|
+
| [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 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#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 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]]
 +
|}
 +
 +
= 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.