Changes

Jump to navigation Jump to search
2,987 bytes added ,  21:27, 15 October 2023
no edit summary
Line 1: Line 1:  
This is the metadata file that ends in <code>".cnmt{.nca}"</code> or <code>"meta0.ncd"</code>. This seems to replace the TMD format.
 
This is the metadata file that ends in <code>".cnmt{.nca}"</code> or <code>"meta0.ncd"</code>. This seems to replace the TMD format.
   −
There's at least 9 different filenames used for ".cnmt":
+
The official name for CNMT is "PackagedContentMeta".
* "Application_{lower-case hex titleID}.cnmt"
+
 
* "Patch_{lower-case hex titleID}.cnmt"
+
= PackagedContentMetaHeader =
* "AddOnContent_{lower-case hex titleID}.cnmt"
+
This is "nn::ncm::PackagedContentMetaHeader".
* "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 20: 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 67: 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 83: 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 99: 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 119: 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 150: 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 183: 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 259: 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 305: 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 343: 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 381: 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 431: 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.

Navigation menu