Difference between revisions of "NCM services"

From Nintendo Switch Brew
Jump to navigation Jump to search
(4 intermediate revisions by 2 users not shown)
Line 9: Line 9:
 
! Cmd || Name || Arguments || Notes
 
! Cmd || Name || Arguments || Notes
 
|-
 
|-
| 0 || OpenLocationResolver || [[#StorageId|StorageID]] ||
+
| 0 || OpenLocationResolver || [[#StorageId]] ||
 
|-
 
|-
 
| 1 || OpenRegisteredLocationResolver || None ||  
 
| 1 || OpenRegisteredLocationResolver || None ||  
 
|-
 
|-
| 2 || RefreshLocationResolver || [[#StorageId|StorageID]] ||
+
| 2 || RefreshLocationResolver || [[#StorageId]] ||
 
|-
 
|-
 
| 3 || [2.0.0+] OpenAddOnContentLocationResolver || None  ||
 
| 3 || [2.0.0+] OpenAddOnContentLocationResolver || None  ||
Line 68: Line 68:
 
|}
 
|}
  
If the supplied [[#StorageId|StorageID]] is 1 (Host), a different set of internal functions is used to handle these commands. In this more restricted set of functions, GetControlNcaPath is stubbed and only returns error 0x608.
+
If the supplied [[#StorageId]] is 1 (Host), a different set of internal functions is used to handle these commands. In this more restricted set of functions, [[#ResolveApplicationControlPath]] is stubbed and only returns error 0x608.
  
The Get* commands load the [[Filesystem_services|ContentPath]] from linked-lists' [[#Location_List_Entry|entries]] in memory using the input [[#ProgramId]]. When the command fails to find an entry for the specified [[#ProgramId]], 0x408 is returned for GetProgramNcaPath and 0xA08 is returned for the rest.
+
The Get* commands load the [[Filesystem_services#ContentPath|ContentPath]] from linked-lists' [[#Location_List_Entry|entries]] in memory using the input [[#ProgramId]]. When the command fails to find an entry for the specified [[#ProgramId]], 0x408 is returned for [[#ResolveProgramPath]] and 0xA08 is returned for the rest.
  
 
The Set* commands always return 0 and add a new entry to the list. If a matching entry is found, it's removed first.
 
The Set* commands always return 0 and add a new entry to the list. If a matching entry is found, it's removed first.
  
 
==== ResolveProgramPath ====
 
==== ResolveProgramPath ====
Takes an u64 [[#ProgramId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
+
Takes an [[#ProgramId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
  
 
==== RedirectProgramPath ====
 
==== RedirectProgramPath ====
Takes an u64 [[#ProgramId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
+
Takes an [[#ProgramId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
  
 
Inserts a new [[#Location_List_Entry|entry]] with '''flag''' set to 0.
 
Inserts a new [[#Location_List_Entry|entry]] with '''flag''' set to 0.
  
 
==== ResolveApplicationControlPath ====
 
==== ResolveApplicationControlPath ====
Takes an u64 [[#ApplicationId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
+
Takes an [[#ApplicationId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
  
 
==== ResolveApplicationHtmlDocumentPath====
 
==== ResolveApplicationHtmlDocumentPath====
Takes an u64 [[#ApplicationId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type4|NCA-type4]].
+
Takes an [[#ApplicationId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type4|NCA-type4]].
  
 
==== ResolveDataPath ====
 
==== ResolveDataPath ====
Takes an u64 [[#ApplicationId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
+
Takes an [[#DataId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
  
 
==== RedirectApplicationControlPath ====
 
==== RedirectApplicationControlPath ====
Takes an u64 [[#ApplicationId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
+
Takes an [[#ApplicationId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
  
 
[9.0.0+] Now takes an additional 8-bytes of input.
 
[9.0.0+] Now takes an additional 8-bytes of input.
Line 99: Line 99:
  
 
==== RedirectApplicationHtmlDocumentPath ====
 
==== RedirectApplicationHtmlDocumentPath ====
Takes an u64 [[#ApplicationId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type4|NCA-type4]].
+
Takes an [[#ApplicationId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type4|NCA-type4]].
  
 
[9.0.0+] Now takes an additional 8-bytes of input.
 
[9.0.0+] Now takes an additional 8-bytes of input.
Line 106: Line 106:
  
 
==== ResolveApplicationLegalInformationPath ====
 
==== ResolveApplicationLegalInformationPath ====
Takes an u64 [[#ApplicationId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type5|NCA-type5]].
+
Takes an [[#ApplicationId]] and a C descriptor. Used for [[NCA_Content_FS#NCA-type5|NCA-type5]].
  
 
==== RedirectApplicationLegalInformationPath ====
 
==== RedirectApplicationLegalInformationPath ====
Takes an u64 [[#ApplicationId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type5|NCA-type5]].
+
Takes an [[#ApplicationId]] and a X descriptor with a [[Filesystem_services#ContentPath|ContentPath]]. Used for [[NCA_Content_FS#NCA-type5|NCA-type5]].
  
 
[9.0.0+] Now takes an additional 8-bytes of input.
 
[9.0.0+] Now takes an additional 8-bytes of input.
Line 129: Line 129:
  
 
==== EraseProgramRedirection ====
 
==== EraseProgramRedirection ====
Takes an u64 [[#ProgramnId]]. Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
+
Takes an [[#ProgramnId]]. Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
  
 
Removes the [[#Location_List_Entry|entry]] that matches the input ProgramId.
 
Removes the [[#Location_List_Entry|entry]] that matches the input ProgramId.
  
 
==== EraseApplicationControlRedirection ====
 
==== EraseApplicationControlRedirection ====
Takes an u64 [[#ApplicationId]]. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
+
Takes an [[#ApplicationId]]. Used for [[NCA_Content_FS#NCA-type3|NCA-type3]].
  
 
Removes the [[#Location_List_Entry|entry]] that matches the input ApplicationId.
 
Removes the [[#Location_List_Entry|entry]] that matches the input ApplicationId.
  
 
==== EraseApplicationHtmlDocumentRedirection ====
 
==== EraseApplicationHtmlDocumentRedirection ====
Takes an u64 [[#ApplicationId]]. Used for [[NCA_Content_FS#NCA-type4|NCA-type4]].
+
Takes an [[#ApplicationId]]. Used for [[NCA_Content_FS#NCA-type4|NCA-type4]].
  
 
Removes the [[#Location_List_Entry|entry]] that matches the input ApplicationId.
 
Removes the [[#Location_List_Entry|entry]] that matches the input ApplicationId.
  
 
==== EraseApplicationLegalInformationRedirection ====
 
==== EraseApplicationLegalInformationRedirection ====
Takes an u64 [[#ApplicationId]]. Used for [[NCA_Content_FS#NCA-type5|NCA-type5]].
+
Takes an [[#ApplicationId]]. Used for [[NCA_Content_FS#NCA-type5|NCA-type5]].
  
 
Removes the [[#Location_List_Entry|entry]] that matches the input ApplicationId.
 
Removes the [[#Location_List_Entry|entry]] that matches the input ApplicationId.
Line 179: Line 179:
 
! Cmd || Name || Arguments || Notes
 
! Cmd || Name || Arguments || Notes
 
|-
 
|-
| 0 || ResolveProgramPath || u64 [[#ProgramId]] + C descriptor || Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
+
| 0 || ResolveProgramPath || [[#ProgramId]] + C descriptor || Used for [[NCA_Content_FS#NCA-type1|NCA-type1]].
 
|-
 
|-
| 1 || RegisterProgramPath || u64 [[#ProgramId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. || Sets the Type 0 fallback TID and path to the provided arguments.
+
| 1 || RegisterProgramPath || [[#ProgramId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. || Sets the Type 0 fallback TID and path to the provided arguments.
 
|-
 
|-
| 2 || UnregisterProgramPath || u64 [[#ProgramId]] || If the Type 0 fallback TID is == argument TID, unregisters the fallback path. Otherwise, noop.
+
| 2 || UnregisterProgramPath || [[#ProgramId]] || If the Type 0 fallback TID is == argument TID, unregisters the fallback path. Otherwise, noop.
 
|-
 
|-
| 3 || RedirectProgramPath || u64 [[#ProgramId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. ||
+
| 3 || RedirectProgramPath || [[#ProgramId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. ||
 
|-
 
|-
| 4 || [2.0.0+] ResolveHtmlDocumentPath || u64 [[#ProgramId]] + C descriptor ||
+
| 4 || [2.0.0+] ResolveHtmlDocumentPath || [[#ApplicationId]] + C descriptor ||
 
|-
 
|-
| 5 || [2.0.0+] RegisterHtmlDocumentPath || u64 [[#ProgramId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. || Sets the Type 1 fallback TID and path to the provided arguments.
+
| 5 || [2.0.0+] RegisterHtmlDocumentPath || [[#ApplicationId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. || Sets the Type 1 fallback TID and path to the provided arguments.
 
|-
 
|-
| 6 || [2.0.0+] UnregisterHtmlDocumentPath || u64 [[#ProgramId]] || If the Type 1 fallback TID is == argument TID, unregisters the fallback path. Otherwise, noop.
+
| 6 || [2.0.0+] UnregisterHtmlDocumentPath || [[#ApplicationId]] || If the Type 1 fallback TID is == argument TID, unregisters the fallback path. Otherwise, noop.
 
|-
 
|-
| 7 || [2.0.0+] RedirectHtmlDocumentPath || u64 [[#ProgramId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. ||
+
| 7 || [2.0.0+] RedirectHtmlDocumentPath || [[#ApplicationId]] + X descriptor [[Filesystem_services#ContentPath|ContentPath]] [9.0.0+] Now takes an additional 8-bytes of input. ||
 
|-
 
|-
 
| 8 || [7.0.0+] Refresh || No input/output. ||  
 
| 8 || [7.0.0+] Refresh || No input/output. ||  
Line 207: Line 207:
 
! Cmd || Name || Arguments || Notes
 
! Cmd || Name || Arguments || Notes
 
|-
 
|-
| 0 || ResolveAddOnContentPath || u64 [[#ProgramId]] + C descriptor ||  
+
| 0 || ResolveAddOnContentPath || [[#ApplicationId]] + C descriptor ||  
 
|-
 
|-
| 1 || RegisterAddOnContentStorage || [[#StorageId|StorageID]] + u64 [[#ProgramId]] [9.0.0+] Now takes an additional u64 [[#ApplicationId]] for the owner application. ||  
+
| 1 || RegisterAddOnContentStorage || [[#StorageId]] + [[#ApplicationId]] [9.0.0+] Now takes an additional [[#ApplicationId]] for the owner application. ||  
 
|-
 
|-
 
| 2 || UnregisterAllAddOnContentPath || None || Clears all registered titles here.
 
| 2 || UnregisterAllAddOnContentPath || None || Clears all registered titles here.
Line 215: Line 215:
 
| 3 || [9.0.0+] [[#RefreshApplicationAddOnContent]] || Type-5 buffer || Unofficial name
 
| 3 || [9.0.0+] [[#RefreshApplicationAddOnContent]] || Type-5 buffer || Unofficial name
 
|-
 
|-
| 4 || [9.0.0+] [[#UnregisterApplicationAddOnContent]] || u64 [[#ProgramId]] || Unofficial name
+
| 4 || [9.0.0+] [[#UnregisterApplicationAddOnContent]] || [[#ApplicationId]] || Unofficial name
 
|}
 
|}
  
Line 222: Line 222:
  
 
==== UnregisterApplicationAddOnContent====
 
==== UnregisterApplicationAddOnContent====
Takes an u64 [[#ApplicationId]] for the application to unregister add on content entries for.
+
Takes an [[#ApplicationId]] for the application to unregister add on content entries for.
  
 
=== Location List Entry ===
 
=== Location List Entry ===
Line 237: Line 237:
 
| 0x10 || 0x8|| [[#ProgramId]]
 
| 0x10 || 0x8|| [[#ProgramId]]
 
|-
 
|-
| 0x18 || 0x300 || [[#Path]]
+
| 0x18 || 0x300 || [[Filesystem_services#ContentPath|ContentPath]]
 
|-
 
|-
 
| 0x318 || 0x4 || Flag
 
| 0x318 || 0x4 || Flag
Line 252: Line 252:
 
! Cmd || Name || Notes
 
! Cmd || Name || Notes
 
|-
 
|-
| 0 || CreateContentStorage || Takes a [[#StorageId|StorageID]].
+
| 0 || CreateContentStorage || Takes a [[#StorageId]].
 
|-
 
|-
| 1 || CreateContentMetaDatabase || Takes a [[#StorageId|StorageID]].
+
| 1 || CreateContentMetaDatabase || Takes a [[#StorageId]].
 
|-
 
|-
| 2 || VerifyContentStorage || Takes a [[#StorageId|StorageID]].
+
| 2 || VerifyContentStorage || Takes a [[#StorageId]].
 
|-
 
|-
| 3 || VerifyContentMetaDatabase || Takes a [[#StorageId|StorageID]].
+
| 3 || VerifyContentMetaDatabase || Takes a [[#StorageId]].
 
|-
 
|-
| 4 || OpenContentStorage || Takes a [[#StorageId|StorageID]], [2.0.0+] Only returns a storage if one has previously been opened globally via OpenIContentStorage.
+
| 4 || OpenContentStorage || Takes a [[#StorageId]], [2.0.0+] Only returns a storage if one has previously been opened globally via CreateContentStorage.
 
|-
 
|-
| 5 || OpenContentMetaDatabase || Takes a [[#StorageId|StorageID]], [2.0.0+] Only returns a storage if one has previously been opened globally via OpenIContentStorage.
+
| 5 || OpenContentMetaDatabase || Takes a [[#StorageId]], [2.0.0+] Only returns a storage if one has previously been opened globally via CreateContentStorage.
 
|-
 
|-
| 6 || [1.0.0] CloseContentStorageForcibly || Takes a [[#StorageId|StorageID]]. Calls IContentStorage->CloseAndFlushStorage().
+
| 6 || [1.0.0] CloseContentStorageForcibly || Takes a [[#StorageId]]. Calls IContentStorage->DisableForcibly().
 
|-
 
|-
| 7 || [1.0.0] CloseContentMetaDatabaseForcibly || Takes a [[#StorageId|StorageID]].  Calls IContentMetaDatabase->CloseMetaDatabase().
+
| 7 || [1.0.0] CloseContentMetaDatabaseForcibly || Takes a [[#StorageId]].  Calls IContentMetaDatabase->DisableForcibly().
 
|-
 
|-
| 8 || CleanupContentMetaDatabase || Takes a [[#StorageId|StorageID]], and deletes the associated savedata.
+
| 8 || CleanupContentMetaDatabase || Takes a [[#StorageId]], and deletes the associated savedata.
 
|-
 
|-
| 9 || [2.0.0+] ActivateContentStorage || Takes a [[#StorageId|StorageID]], and opens an IContentStorage for the StorageID to be gotten with GetIContentStorage. Note: Name is not official.
+
| 9 || [2.0.0+] ActivateContentStorage || Takes a [[#StorageId]], and opens an IContentStorage for the StorageID to be gotten with GetIContentStorage. Note: Name is not official.
 
|-
 
|-
| 10 || [2.0.0+] InactivateContentStorage || Takes a [[#StorageId|StorageID]], and closes the associated IContentStorage. Note: Name is not official.
+
| 10 || [2.0.0+] InactivateContentStorage || Takes a [[#StorageId]], and closes the associated IContentStorage.
 
|-
 
|-
| 11 || [2.0.0+] ActivateContentMetaDatabase || Takes a [[#StorageId|StorageID]], and opens an IContentMetaDatabase for the StorageID to be gotten with GetIContentMetaDatabase. Note: Name is not official.
+
| 11 || [2.0.0+] ActivateContentMetaDatabase || Takes a [[#StorageId]], and opens an IContentMetaDatabase for the StorageID to be gotten with CreateContentMetaDatabase.
 
|-
 
|-
| 12 || [2.0.0+] InactivateContentMetaDatabase || Takes a [[#StorageId|StorageID]], and closes the associated IContentMetaDatabase. Note: Name is not official.
+
| 12 || [2.0.0+] InactivateContentMetaDatabase || Takes a [[#StorageId]], and closes the associated IContentMetaDatabase.
 
|-
 
|-
 
| 13 || [9.0.0+] InvalidateRightsIdCache ||
 
| 13 || [9.0.0+] InvalidateRightsIdCache ||
Line 304: Line 304:
 
| 7 || Has || Takes a [[#ContentId]].
 
| 7 || Has || Takes a [[#ContentId]].
 
|-
 
|-
| 8 || GetPath || Takes a [[#ContentId]] and a type-0x1A output buffer containing a [[#Path]].
+
| 8 || GetPath || Takes a [[#ContentId]] and a type-0x1A output buffer containing a [[Filesystem_services#ContentPath|ContentPath]].
 
|-
 
|-
| 9 || GetPlaceHolderPath || Takes a [[#PlaceHolderId]] and a type-0x1A output buffer containing a [[#Path]].
+
| 9 || GetPlaceHolderPath || Takes a [[#PlaceHolderId]] and a type-0x1A output buffer containing a [[Filesystem_services#ContentPath|ContentPath]].
 
|-
 
|-
 
| 10 || CleanupAllPlaceHolder || No input/output. Deletes and re-creates the Placeholder directory.
 
| 10 || CleanupAllPlaceHolder || No input/output. Deletes and re-creates the Placeholder directory.
Line 320: Line 320:
 
| 15 || DisableForcibly || No input/output. Closes/Flushes all resources for the storage, and causes all future IPC commands to the current session to return error 0xC805.
 
| 15 || DisableForcibly || No input/output. Closes/Flushes all resources for the storage, and causes all future IPC commands to the current session to return error 0xC805.
 
|-
 
|-
| 16 || [2.0.0+] RevertToPlaceHolder || Takes a [[#ContentId]], a [[#ContentId]], and a [[#PlaceHolderId]], no output. Creates the registered directory NCA path, and renames the placeholder path to the registered NCA path.
+
| 16 || [2.0.0+] RevertToPlaceHolder || Takes two [[#ContentId]] and a [[#PlaceHolderId]], no output. Creates the registered directory NCA path, and renames the placeholder path to the registered NCA path.
 
|-
 
|-
 
| 17 || [2.0.0+] SetPlaceHolderSize || Takes a [[#PlaceHolderId]], and a s64 size, no output.
 
| 17 || [2.0.0+] SetPlaceHolderSize || Takes a [[#PlaceHolderId]], and a s64 size, no output.
Line 388: Line 388:
 
! Cmd || Name || Notes
 
! Cmd || Name || Notes
 
|-
 
|-
| 0 || Set || Takes a [[#ContentMetaKey|Content Meta Key]], a type-5 [[CNMT#Content_records|Content Records]] buffer and a u64 size.
+
| 0 || Set || Takes a [[#ContentMetaKey]], a type-5 [[CNMT#Content_Records|Content Records]] buffer and a u64 size.
 
|-
 
|-
| 1 || Get || Takes a [[#ContentMetaKey|Content Meta Key]], a type-6 buffer to write [[CNMT#Content_records|Content Records]] to and a u64 size. Returns the actual number of bytes read into the buffer. First 8 bytes of the data is header (u16 numExtraDataBytes, numContentRecords, numMetaRecords, padding). After the header is numExtraDataBytes of additional data, after which follow content records and content meta keys. Set takes this same data as input.
+
| 1 || Get || Takes a [[#ContentMetaKey]], a type-6 buffer to write [[CNMT#Content_Records|Content Records]] to and a u64 size. Returns the actual number of bytes read into the buffer. First 8 bytes of the data is header (u16 numExtraDataBytes, numContentRecords, numMetaRecords, padding). After the header is numExtraDataBytes of additional data, after which follow content records and content meta keys. Set takes this same data as input.
 
|-
 
|-
| 2 || Remove || Takes a [[#ContentMetaKey|Content Meta Key]], and removes the associated record.
+
| 2 || Remove || Takes a [[#ContentMetaKey]], and removes the associated record.
 
|-
 
|-
| 3 || GetContentIdByType || Takes a [[#ContentMetaKey|Content Meta Key]] and a u8 [[#ContentMetaType|Content Meta Type]]. Returns a [[#ContentId]].
+
| 3 || GetContentIdByType || Takes a [[#ContentMetaKey]] and a u8 [[#ContentMetaType]]. Returns a [[#ContentId]].
 
|-
 
|-
| 4 || ListContentInfo || Takes a type-6 buffer to write [[CNMT#Content_records|Content Record]] entries to, a [[#ContentMetaKey|Content Meta Key]], and a s32 index into the Content Record entries to start copying from. Returns a s32 entries_read.
+
| 4 || ListContentInfo || Takes a type-6 buffer to write [[CNMT#Content_Records|Content Record]] entries to, a [[#ContentMetaKey]], and a s32 index into the Content Record entries to start copying from. Returns a s32 entries_read.
 
|-
 
|-
| 5 || List || Takes a type-6 buffer to write [[#ContentMetaKey|Content Meta Key]]s to, a u32 [[#ContentMetaType|Content Meta Type]], a u64 TID, a u64 TID_LOW, and u64 TID_HIGH. Writes into the buffer all Content Meta Keys with low <= record->title_id <= high, and record->type == type. Returns s32 numEntriesTotal, numEntriesWritten. Additionally requires record->title_id == TID, if record->type is Application, Patch, Add-On, or Delta, otherwise, you can pass 0 for type to ignore the type and list them all in the range.
+
| 5 || List || Takes a type-6 buffer to write [[#ContentMetaKey]]s to, a u32 [[#ContentMetaType]], a [[#ProgramId]], a u64 ProgramId_Low, and u64 ProgramId_High. Writes into the buffer all Content Meta Keys with low <= record->title_id <= high, and record->type == type. Returns s32 numEntriesTotal, numEntriesWritten. Additionally requires record->title_id == TID, if record->type is Application, Patch, Add-On, or Delta, otherwise, you can pass 0 for type to ignore the type and list them all in the range.
 
|-
 
|-
| 6 || GetLatestContentMetaKey || Takes a u64 [[#ProgramId]], and returns the [[#ContentMetaKey|Content Meta Key]] with the highest version field for that ProgramId.
+
| 6 || GetLatestContentMetaKey || Takes a [[#ProgramId]], and returns the [[#ContentMetaKey]] with the highest version field for that ProgramId.
 
|-
 
|-
 
| 7 || [[#ListApplication]] ||
 
| 7 || [[#ListApplication]] ||
 
|-
 
|-
| 8 || Has || Takes a [[#ContentMetaKey|Content Meta Key]] and returns an output u8 bool indicating whether that record is present in the database.
+
| 8 || Has || Takes a [[#ContentMetaKey]] and returns an output u8 bool indicating whether that record is present in the database.
 
|-
 
|-
| 9 || HasAll || Takes a type-0x5 input buffer containing an array of [[#ContentMetaKey|Content Meta Key]], and returns whether all of those records are present in the database.
+
| 9 || HasAll || Takes a type-0x5 input buffer containing an array of [[#ContentMetaKey]], and returns whether all of those records are present in the database.
 
|-
 
|-
| 10 || GetSize || Takes a [[#ContentMetaKey|Content Meta Key]], and returns the size of the associated [[CNMT#Content_records|Content Records]].
+
| 10 || GetSize || Takes a [[#ContentMetaKey]], and returns the size of the associated [[CNMT#Content_Records|Content Records]].
 
|-
 
|-
| 11 || GetRequiredSystemVersion || Takes a [[#ContentMetaKey|Content Meta Key]], and returns u32 from ContentRecords + 16 (only if the content meta key has type Application or Patch).
+
| 11 || GetRequiredSystemVersion || Takes a [[#ContentMetaKey]], and returns u32 from ContentRecords + 16 (only if the content meta key has type Application or Patch).
 
|-
 
|-
| 12 || GetPatchId || Takes a [[#ContentMetaKey|Content Meta Key]], and returns the update [[#ProgramId]] for that record.
+
| 12 || GetPatchId || Takes a [[#ContentMetaKey]], and returns the update [[#ProgramId]] for that record.
 
|-
 
|-
| 13 || DisableForcibly || Closes the meta database, and causes all future IPC commands to the current session to return error 0xDC05.
+
| 13 || DisableForcibly || Closes the meta database, and causes all future IPC commands to the current session to return error 0xDC05.
 
|-
 
|-
 
| 14 || [[#LookupOrphanContent]] || Takes a type-6 byte buffer, and a type-5 buffer of [[#ContentId]]s.
 
| 14 || [[#LookupOrphanContent]] || Takes a type-6 byte buffer, and a type-5 buffer of [[#ContentId]]s.
Line 420: Line 420:
 
| 15 || Commit || Flushes the in-memory database to savedata.
 
| 15 || Commit || Flushes the in-memory database to savedata.
 
|-
 
|-
| 16 || HasContent || Takes a [[#ContentMetaKey|Content Meta Key]] and an [[#ContentId]]. Returns whether the content records for that content meta key contain the ContentId.
+
| 16 || HasContent || Takes a [[#ContentMetaKey]] and an [[#ContentId]]. Returns whether the content records for that content meta key contain the ContentId.
 
|-
 
|-
| 17 || ListContentMetaInfo || Takes a type-6 [[#ContentMetaKey|Content Meta Key]] output buffer, a s32 offset into that buffer, and an input [[#ContentMetaKey|Content Meta Key]].
+
| 17 || ListContentMetaInfo || Takes a type-6 [[#ContentMetaKey]] output buffer, a s32 offset into that buffer, and an input [[#ContentMetaKey]].
 
|-
 
|-
| 18 || GetAttributes || Takes a [[#ContentMetaKey|Content Meta Key]], and returns u8 from ContentRecords + 6.
+
| 18 || GetAttributes || Takes a [[#ContentMetaKey]], and returns u8 from ContentRecords + 6.
 
|-
 
|-
| 19 || [2.0.0+] GetRequiredApplicationVersion || Does the same thing as GetEntryUnknownRecordSize, but for AddOnContents.
+
| 19 || [2.0.0+] GetRequiredApplicationVersion || Does the same thing as GetRequiredSystemVersion, but for AddOnContents.
 
|-
 
|-
 
| 20 || [5.0.0+] GetContentIdByTypeAndIdOffset ||
 
| 20 || [5.0.0+] GetContentIdByTypeAndIdOffset ||
Line 441: Line 441:
  
 
==== ReadEntryMetaRecords ====
 
==== ReadEntryMetaRecords ====
Takes a type-6 [[#ContentMetaKey|Content Meta Key]] output buffer, a s32 offset into that buffer, and an input [[#ContentMetaKey|Content Meta Key]] entry. Returns a s32 for total_read_entries.
+
Takes a type-6 [[#ContentMetaKey]] output buffer, a s32 offset into that buffer, and an input [[#ContentMetaKey]] entry. Returns a s32 for total_read_entries.
  
 
Reads the content meta keys stored in the entry's content records into the output buffer.
 
Reads the content meta keys stored in the entry's content records into the output buffer.
Line 486: Line 486:
  
 
== ApplicationId ==
 
== ApplicationId ==
This is "nn::ncm::ApplicationId".
+
This is "nn::ncm::ApplicationId" or "nn::ncm::SystemApplicationId".
  
 
This is an u64 ID bound to an [[Title_list#System_Applications|application]].
 
This is an u64 ID bound to an [[Title_list#System_Applications|application]].
 +
 +
== PatchId ==
 +
This is "nn::ncm::PatchId".
 +
 +
This is an u64 ID bound to a program patch.
 +
 +
== DeltaId ==
 +
This is "nn::ncm::DeltaId".
 +
 +
This is an u64 ID bound to a program delta fragment.
 +
 +
== AddOnContentId ==
 +
This is "nn::ncm::AddOnContentId".
 +
 +
This is an u64 ID bound to add-on content data.
 +
 +
== SystemUpdateId ==
 +
This is "nn::ncm::SystemUpdateId".
 +
 +
This is an u64 ID bound to system update data.
  
 
== StorageId ==
 
== StorageId ==
This is "nn::ncm::StorageId". Enum, sizeof() == sizeof(u8).
+
This is "nn::ncm::StorageId".
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 519: Line 539:
  
 
== RightsId ==
 
== RightsId ==
This is "nn::ncm::RightsId". This is a 0x10-byte struct. [3.0.0+] This is a 0x18-byte struct.
+
This is "nn::ncm::RightsId".
 +
 
 +
This is a 0x10-byte struct. [3.0.0+] This is a 0x18-byte struct.
  
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
Line 529: Line 551:
 
| 0x0 || 0x10 || FS Rights ID
 
| 0x0 || 0x10 || FS Rights ID
 
|-
 
|-
| 0x10 || 0x1 || [3.0.0+] key_generation
+
| 0x10 || 0x1 || [3.0.0+] KeyGeneration
 
|-
 
|-
 
| 0x11 || 0x7 || [3.0.0+] Padding
 
| 0x11 || 0x7 || [3.0.0+] Padding
Line 553: Line 575:
 
This is "nn::ncm::Path".
 
This is "nn::ncm::Path".
  
This is a 0x300-byte structure, which contains a [[Filesystem_services#ContentPath|Content Path]].
+
This is a 0x300-byte structure, which contains a [[Filesystem_services#ContentPath|ContentPath]].
  
 
== ContentInstallType ==
 
== ContentInstallType ==

Revision as of 17:25, 30 November 2019

NCM contains services for internal file path and content management.

Location Resolver services

lr

This is "nn::lr::ILocationResolverManager".

Cmd Name Arguments Notes
0 OpenLocationResolver #StorageId
1 OpenRegisteredLocationResolver None
2 RefreshLocationResolver #StorageId
3 [2.0.0+] OpenAddOnContentLocationResolver None

The only sysmodules which use this service are FS, Loader, and NS. boot2 has access but doesn't use it.

ILocationResolver

This is "nn::lr::ILocationResolver".

Cmd Name Notes
0 #ResolveProgramPath
1 #RedirectProgramPath
2 #ResolveApplicationControlPath
3 #ResolveApplicationHtmlDocumentPath
4 #ResolveDataPath
5 #RedirectApplicationControlPath
6 #RedirectApplicationHtmlDocumentPath
7 #ResolveApplicationLegalInformationPath
8 #RedirectApplicationLegalInformationPath
9 #Refresh
10 [5.0.0+] #RedirectApplicationProgramPath
11 [5.0.0+] #ClearApplicationRedirection
12 [5.0.0+] #EraseProgramRedirection
13 [5.0.0+] #EraseApplicationControlRedirection
14 [5.0.0+] #EraseApplicationHtmlDocumentRedirection
15 [5.0.0+] #EraseApplicationLegalInformationRedirection
16 [7.0.0+] #ResolveProgramPathForDebug Unofficial name
17 [7.0.0+] #RedirectProgramPathForDebug Unofficial name
18 [7.0.0+] #RedirectApplicationProgramPathForDebug Unofficial name
19 [7.0.0+] #EraseProgramRedirectionForDebug Unofficial name

If the supplied #StorageId is 1 (Host), a different set of internal functions is used to handle these commands. In this more restricted set of functions, #ResolveApplicationControlPath is stubbed and only returns error 0x608.

The Get* commands load the ContentPath from linked-lists' entries in memory using the input #ProgramId. When the command fails to find an entry for the specified #ProgramId, 0x408 is returned for #ResolveProgramPath and 0xA08 is returned for the rest.

The Set* commands always return 0 and add a new entry to the list. If a matching entry is found, it's removed first.

ResolveProgramPath

Takes an #ProgramId and a C descriptor. Used for NCA-type1.

RedirectProgramPath

Takes an #ProgramId and a X descriptor with a ContentPath. Used for NCA-type1.

Inserts a new entry with flag set to 0.

ResolveApplicationControlPath

Takes an #ApplicationId and a C descriptor. Used for NCA-type3.

ResolveApplicationHtmlDocumentPath

Takes an #ApplicationId and a C descriptor. Used for NCA-type4.

ResolveDataPath

Takes an #DataId and a C descriptor. Used for NCA-type3.

RedirectApplicationControlPath

Takes an #ApplicationId and a X descriptor with a ContentPath. Used for NCA-type3.

[9.0.0+] Now takes an additional 8-bytes of input.

Inserts a new entry with flag set to 1.

RedirectApplicationHtmlDocumentPath

Takes an #ApplicationId and a X descriptor with a ContentPath. Used for NCA-type4.

[9.0.0+] Now takes an additional 8-bytes of input.

Inserts a new entry with flag set to 1.

ResolveApplicationLegalInformationPath

Takes an #ApplicationId and a C descriptor. Used for NCA-type5.

RedirectApplicationLegalInformationPath

Takes an #ApplicationId and a X descriptor with a ContentPath. Used for NCA-type5.

[9.0.0+] Now takes an additional 8-bytes of input.

Inserts a new entry with flag set to 1.

Refresh

Takes no input. Frees all linked-lists' entries that have flag set to 0.

RedirectApplicationProgramPath

Same as RedirectProgramPath, but inserts a new entry with flag set to 1.

[9.0.0+] Now takes an additional 8-bytes of input.

ClearApplicationRedirection

Takes no input. Frees all linked-lists' entries that have flag set to 1.

[9.0.0+] Now takes a type-0x5 input buffer, no output.

EraseProgramRedirection

Takes an #ProgramnId. Used for NCA-type1.

Removes the entry that matches the input ProgramId.

EraseApplicationControlRedirection

Takes an #ApplicationId. Used for NCA-type3.

Removes the entry that matches the input ApplicationId.

EraseApplicationHtmlDocumentRedirection

Takes an #ApplicationId. Used for NCA-type4.

Removes the entry that matches the input ApplicationId.

EraseApplicationLegalInformationRedirection

Takes an #ApplicationId. Used for NCA-type5.

Removes the entry that matches the input ApplicationId.

ResolveProgramPathForDebug

Same as ResolveProgramPath, but uses a redirection shim on top of the real program path.

NS uses this command if ns.application!redirected_rom_storage_id_for_debug is different than 0x00.

RedirectProgramPathForDebug

Same as RedirectProgramPath, but uses a redirection shim on top of the real program path.

NS uses this command if ns.application!redirected_rom_storage_id_for_debug is different than 0x00.

RedirectApplicationProgramPathForDebug

Same as RedirectApplicationProgramPath , but uses a redirection shim on top of the real program path.

[9.0.0+] Like #RedirectApplicationProgramPath this now takes an additional 8-bytes of input.

NS uses this command if ns.application!redirected_rom_storage_id_for_debug is different than 0x00.

EraseProgramRedirectionForDebug

Same as EraseProgramRedirection , but uses a redirection shim on top of the real program path.

NS uses this command if ns.application!redirected_rom_storage_id_for_debug is different than 0x00.

IRegisteredLocationResolver

This is "nn::lr::IRegisteredLocationResolver".

This works like #ILocationResolver, but only two types of NCA paths can be gotten/set. In addition, each type has a fallback path that can be set for a single #ProgramId at a time.

Cmd Name Arguments Notes
0 ResolveProgramPath #ProgramId + C descriptor Used for NCA-type1.
1 RegisterProgramPath #ProgramId + X descriptor ContentPath [9.0.0+] Now takes an additional 8-bytes of input. Sets the Type 0 fallback TID and path to the provided arguments.
2 UnregisterProgramPath #ProgramId If the Type 0 fallback TID is == argument TID, unregisters the fallback path. Otherwise, noop.
3 RedirectProgramPath #ProgramId + X descriptor ContentPath [9.0.0+] Now takes an additional 8-bytes of input.
4 [2.0.0+] ResolveHtmlDocumentPath #ApplicationId + C descriptor
5 [2.0.0+] RegisterHtmlDocumentPath #ApplicationId + X descriptor ContentPath [9.0.0+] Now takes an additional 8-bytes of input. Sets the Type 1 fallback TID and path to the provided arguments.
6 [2.0.0+] UnregisterHtmlDocumentPath #ApplicationId If the Type 1 fallback TID is == argument TID, unregisters the fallback path. Otherwise, noop.
7 [2.0.0+] RedirectHtmlDocumentPath #ApplicationId + X descriptor ContentPath [9.0.0+] Now takes an additional 8-bytes of input.
8 [7.0.0+] Refresh No input/output.
9 [9.0.0+] RefreshExcluding Type-5 buffer Unofficial name. Refreshes entries excluding those with application ProgramIds contained in the buffer.

IAddOnContentLocationResolver

This is "nn::lr::IAddOnContentLocationResolver".

Cmd Name Arguments Notes
0 ResolveAddOnContentPath #ApplicationId + C descriptor
1 RegisterAddOnContentStorage #StorageId + #ApplicationId [9.0.0+] Now takes an additional #ApplicationId for the owner application.
2 UnregisterAllAddOnContentPath None Clears all registered titles here.
3 [9.0.0+] #RefreshApplicationAddOnContent Type-5 buffer Unofficial name
4 [9.0.0+] #UnregisterApplicationAddOnContent #ApplicationId Unofficial name

RefreshApplicationAddOnContent

Takes an type-5 buffer containing an array of #ApplicationId. Unregisters entries with IDs absent from the input buffer.

UnregisterApplicationAddOnContent

Takes an #ApplicationId for the application to unregister add on content entries for.

Location List Entry

Total size is 0x320 bytes.

Offset Size Description
0x0 0x8 Pointer to previous entry
0x8 0x8 Pointer to next entry
0x10 0x8 #ProgramId
0x18 0x300 ContentPath
0x318 0x4 Flag
0x31C 0x4 Padding

Content Manager services

ncm

This is "nn::ncm::IContentManager".

Cmd Name Notes
0 CreateContentStorage Takes a #StorageId.
1 CreateContentMetaDatabase Takes a #StorageId.
2 VerifyContentStorage Takes a #StorageId.
3 VerifyContentMetaDatabase Takes a #StorageId.
4 OpenContentStorage Takes a #StorageId, [2.0.0+] Only returns a storage if one has previously been opened globally via CreateContentStorage.
5 OpenContentMetaDatabase Takes a #StorageId, [2.0.0+] Only returns a storage if one has previously been opened globally via CreateContentStorage.
6 [1.0.0] CloseContentStorageForcibly Takes a #StorageId. Calls IContentStorage->DisableForcibly().
7 [1.0.0] CloseContentMetaDatabaseForcibly Takes a #StorageId. Calls IContentMetaDatabase->DisableForcibly().
8 CleanupContentMetaDatabase Takes a #StorageId, and deletes the associated savedata.
9 [2.0.0+] ActivateContentStorage Takes a #StorageId, and opens an IContentStorage for the StorageID to be gotten with GetIContentStorage. Note: Name is not official.
10 [2.0.0+] InactivateContentStorage Takes a #StorageId, and closes the associated IContentStorage.
11 [2.0.0+] ActivateContentMetaDatabase Takes a #StorageId, and opens an IContentMetaDatabase for the StorageID to be gotten with CreateContentMetaDatabase.
12 [2.0.0+] InactivateContentMetaDatabase Takes a #StorageId, and closes the associated IContentMetaDatabase.
13 [9.0.0+] InvalidateRightsIdCache

IContentStorage

This is "nn::ncm::IContentStorage".

Cmd Name Notes
0 #GeneratePlaceHolderId Returns a random UUID for the Content Storage.
1 CreatePlaceHolder Takes a #ContentId, a #PlaceHolderId, and a s64 filesize.
2 DeletePlaceHolder Takes a #PlaceHolderId.
3 HasPlaceHolder Takes a #PlaceHolderId and returns an output u8 bool.
4 WritePlaceHolder Takes a #PlaceHolderId, a u64-offset, and type-0x5 input buffer. Writes the buffer to the file for the placeholder path at the specified offset.
5 Register Takes a #ContentId and a #PlaceHolderId, no output. Moves the Placeholder NCA content to the registered NCA path.
6 Delete Takes a #ContentId.
7 Has Takes a #ContentId.
8 GetPath Takes a #ContentId and a type-0x1A output buffer containing a ContentPath.
9 GetPlaceHolderPath Takes a #PlaceHolderId and a type-0x1A output buffer containing a ContentPath.
10 CleanupAllPlaceHolder No input/output. Deletes and re-creates the Placeholder directory.
11 ListPlaceHolder This is like #GetNumberOfRegisteredEntries, but for the Placeholder directory.
12 #GetContentCount
13 #ListContentId
14 #GetSizeFromContentId
15 DisableForcibly No input/output. Closes/Flushes all resources for the storage, and causes all future IPC commands to the current session to return error 0xC805.
16 [2.0.0+] RevertToPlaceHolder Takes two #ContentId and a #PlaceHolderId, no output. Creates the registered directory NCA path, and renames the placeholder path to the registered NCA path.
17 [2.0.0+] SetPlaceHolderSize Takes a #PlaceHolderId, and a s64 size, no output.
18 [2.0.0+] #ReadContentIdFile
19 [2.0.0+] #GetRightsIdFromPlaceHolderId
20 [2.0.0+] #GetRightsIdFromContentId
21 [2.0.0+] WriteContentForDebug Takes a #ContentId, a u64 offset, and a type-0x5 input buffer. On debug units, writes the buffer to the NCA's registered path. On retail units, this just aborts.
22 [2.0.0+] GetFreeSpaceSize Gets free space for the storage.
23 [2.0.0+] GetTotalSpaceSize Gets total space for the storage.
24 [3.0.0+] FlushPlaceHolder Flushes resources for the storage without closing it.
25 [4.0.0+] GetSizeFromPlaceHolderId
26 [4.0.0+] RepairInvalidFileAttribute
27 [8.0.0+] GetRightsIdFromPlaceHolderIdWithCache

GeneratePlaceHolderId

Generates a random #PlaceHolderId for use as a placeholder.

Calls nn::util::GenerateUuid(), which internally calls nn::os::GenerateRandomBytes(16);

GetContentCount

Writes the total number of entries which can be read by GetEntries, to cmdreply <SFCO_offset>+0x10.

ListContentId

Takes an output buffer, s32 offset and gets all entries starting at that offset. Returns number of entries read.

Each entry is a #ContentId.

The total read entries is exactly the same as the number of "<hex>.nca" directories in the storage FS(or at least under the "registered" directory?).

GetSizeFromContentId

Takes a #ContentId as input.

Returns the total size readable by #ReadContentIdFile. This is the same as the size-field in the NAX0 "<ContentId>.nca/00" file.

ReadContentIdFile

Takes a type-0x6 output buffer, a #ContentId as input, and a s64 file offset.

Reads plaintext NCA file contents from the Registered path for the ContentId.

GetRightsIdFromPlaceHolderId

Takes a #PlaceHolderId, returns a #RightsId.

Gets the Rights ID for the #PlaceHolderId's placeholder path.

GetRightsIdFromContentId

Takes a #ContentId, returns a #RightsId.

Gets the Rights ID for the #ContentId's registered path

IContentMetaDatabase

This is "nn::ncm::IContentMetaDatabase".

Cmd Name Notes
0 Set Takes a #ContentMetaKey, a type-5 Content Records buffer and a u64 size.
1 Get Takes a #ContentMetaKey, a type-6 buffer to write Content Records to and a u64 size. Returns the actual number of bytes read into the buffer. First 8 bytes of the data is header (u16 numExtraDataBytes, numContentRecords, numMetaRecords, padding). After the header is numExtraDataBytes of additional data, after which follow content records and content meta keys. Set takes this same data as input.
2 Remove Takes a #ContentMetaKey, and removes the associated record.
3 GetContentIdByType Takes a #ContentMetaKey and a u8 #ContentMetaType. Returns a #ContentId.
4 ListContentInfo Takes a type-6 buffer to write Content Record entries to, a #ContentMetaKey, and a s32 index into the Content Record entries to start copying from. Returns a s32 entries_read.
5 List Takes a type-6 buffer to write #ContentMetaKeys to, a u32 #ContentMetaType, a #ProgramId, a u64 ProgramId_Low, and u64 ProgramId_High. Writes into the buffer all Content Meta Keys with low <= record->title_id <= high, and record->type == type. Returns s32 numEntriesTotal, numEntriesWritten. Additionally requires record->title_id == TID, if record->type is Application, Patch, Add-On, or Delta, otherwise, you can pass 0 for type to ignore the type and list them all in the range.
6 GetLatestContentMetaKey Takes a #ProgramId, and returns the #ContentMetaKey with the highest version field for that ProgramId.
7 #ListApplication
8 Has Takes a #ContentMetaKey and returns an output u8 bool indicating whether that record is present in the database.
9 HasAll Takes a type-0x5 input buffer containing an array of #ContentMetaKey, and returns whether all of those records are present in the database.
10 GetSize Takes a #ContentMetaKey, and returns the size of the associated Content Records.
11 GetRequiredSystemVersion Takes a #ContentMetaKey, and returns u32 from ContentRecords + 16 (only if the content meta key has type Application or Patch).
12 GetPatchId Takes a #ContentMetaKey, and returns the update #ProgramId for that record.
13 DisableForcibly Closes the meta database, and causes all future IPC commands to the current session to return error 0xDC05.
14 #LookupOrphanContent Takes a type-6 byte buffer, and a type-5 buffer of #ContentIds.
15 Commit Flushes the in-memory database to savedata.
16 HasContent Takes a #ContentMetaKey and an #ContentId. Returns whether the content records for that content meta key contain the ContentId.
17 ListContentMetaInfo Takes a type-6 #ContentMetaKey output buffer, a s32 offset into that buffer, and an input #ContentMetaKey.
18 GetAttributes Takes a #ContentMetaKey, and returns u8 from ContentRecords + 6.
19 [2.0.0+] GetRequiredApplicationVersion Does the same thing as GetRequiredSystemVersion, but for AddOnContents.
20 [5.0.0+] GetContentIdByTypeAndIdOffset

ListApplication

Each 24-byte entry (officially "ApplicationContentMetaKey") is as follows:

 meta_record meta_record;
 u64    base_title_id;

This function takes in a type 6 buffer to write entries to, and a u8 "filter" type. If filter is zero, all update records will be copied to to the output buffer (space permitting). Otherwise, only titles with type == filter_type will be copied to the output buffer.

This func returns a s32 num_entries_total, and a s32 num_entries_written.

ReadEntryMetaRecords

Takes a type-6 #ContentMetaKey output buffer, a s32 offset into that buffer, and an input #ContentMetaKey entry. Returns a s32 for total_read_entries.

Reads the content meta keys stored in the entry's content records into the output buffer.

This is used, for example, with System Update title 0100000000000816, which contains content meta keys for all other systitles in its Content Records.

LookupOrphanContent

Takes a type-6 byte buffer, and a type-0x5 buffer containing an array of #ContentId.

This function was stubbed to return 0xDC05 in 2.0.0.

On 1.0.0: Initialized the output buffer to all 1s. Then, for each #ContentId in the input buffer, it checks if that ContentId is present anywhere in the database, and if so writes 0 to the corresponding output byte.

In pseudocode, the function basically does the following:

for i in range(len(out_buf)):

   out_buf[i] = 1

for i, ContentId in ContentId:

   if is_present_in_database(ContentId):
       out_buf[i] = 0

ContentId

This is "nn::ncm::ContentId".

This is a 0x10-byte entry. This is originally from the hex portion of "<hex>.nca" directory-names from this storage FS(like SD).

The ContentId is the same as the first 0x10-bytes from the calculated SHA256 hash, from hashing the entire output from #ReadContentIdFile.

PlaceHolderId

This is "nn::ncm::PlaceHolderId".

This is the same as #ContentId, except this is for placeholder content and originates from #GeneratePlaceHolderId.

ProgramId

This is "nn::ncm::ProgramId" or "nn::ncm::SystemProgramId".

This is an u64 ID bound to a program.

DataId

This is "nn::ncm::DataId" or "nn::ncm::SystemDataId".

This is an u64 ID bound to a data archive.

ApplicationId

This is "nn::ncm::ApplicationId" or "nn::ncm::SystemApplicationId".

This is an u64 ID bound to an application.

PatchId

This is "nn::ncm::PatchId".

This is an u64 ID bound to a program patch.

DeltaId

This is "nn::ncm::DeltaId".

This is an u64 ID bound to a program delta fragment.

AddOnContentId

This is "nn::ncm::AddOnContentId".

This is an u64 ID bound to add-on content data.

SystemUpdateId

This is "nn::ncm::SystemUpdateId".

This is an u64 ID bound to system update data.

StorageId

This is "nn::ncm::StorageId".

Value Name
0 None
1 Host
2 GameCard
3 BuiltInSystem
4 BuiltInUser
5 SdCard
6 Any

"None" and "Any" are meta storages.

nn::ncm::IsInstallableStorage returns true for BuiltInSystem, BuiltInUser, SdCard, and Any.

nn::ncm::IsUniqueStorage returns true for != None && != Any.

RightsId

This is "nn::ncm::RightsId".

This is a 0x10-byte struct. [3.0.0+] This is a 0x18-byte struct.

Offset Size Description
0x0 0x10 FS Rights ID
0x10 0x1 [3.0.0+] KeyGeneration
0x11 0x7 [3.0.0+] Padding

ProgramLocation

This is "nn::ncm::ProgramLocation".

Offset Size Description
0x0 0x8 #ProgramId
0x8 0x1 #StorageId
0x9 0x7 Padding

Path

This is "nn::ncm::Path".

This is a 0x300-byte structure, which contains a ContentPath.

ContentInstallType

This is "nn::ncm::ContentInstallType"

Value Description
0x0 Full
0x1 FragmentOnly
0x7 Unknown (Invalid Content Install Type)

ContentMetaType

This is "nn::ncm::ContentMetaType"

Value Description
0x00 Unknown (Invalid Content Meta Type)
0x01 SystemProgram (System Modules or System Applets)
0x02 SystemData (System Data Archives)
0x03 SystemUpdate
0x04 BootImagePackage (Firmware package A or C)
0x05 BootImagePackageSafe (Firmware package B or D)
0x80 Application
0x81 Patch
0x82 AddOnContent
0x83 Delta

ContentMetaKey

This is "nn::ncm::ContentMetaKey"

Offset Size Description
0x0 0x8 #ProgramId
0x8 0x4 Version
0xC 0x1 #ContentMetaType
0xD 0x1 #ContentInstallType
0xE 0x2 Padding

ncm:v

This service doesn't normally exist on retail.