Shared Database services: Difference between revisions

No edit summary
No edit summary
 
(119 intermediate revisions by 5 users not shown)
Line 1: Line 1:
= pl:u =
= pl:s =
This is "nn::pl::detail::IPlatformServiceManager".
This is "nn::pl::detail::IPlatformServiceManagerForSystem". With [16.0.0+] "pl:u" was moved from here to [[Glue_services|glue]].
 
"pl:s" has max_sessions 2 (5 with [16.0.0+]).


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 6: Line 8:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 || [[#RequestSharedFontLoad]]
| 0 || [1.0.0-15.0.1] [[#RequestLoad]]
|-
|-
| 1 || [[#GetSharedFontLoadState]]
| 1 || [1.0.0-15.0.1] [[#GetLoadState]]
|-
|-
| 2 || [[#GetSharedFontSize]]
| 2 || [1.0.0-15.0.1] [[#GetSize]]
|-
|-
| 3 || [[#GetSharedFontAddress]]
| 3 || [1.0.0-15.0.1] [[#GetSharedMemoryAddressOffset]]
|-
|-
| 4 || [[#GetSharedFontSharedMemoryHandle]]
| 4 || [1.0.0-15.0.1] [[#GetSharedMemoryNativeHandle]]
|-
|-
| 5 || [[#GetSharedFontInOrderOfPriority]]
| 5 || [1.0.0-15.0.1] [[#GetSharedFontInOrderOfPriority]]
|-
|-
| 6 || [4.0.0+] GetSharedFontInOrderOfPriorityForSystem
| 6 || [4.0.0-15.0.1] GetSharedFontInOrderOfPriorityForSystem
|-
|-
| 100 || [8.0.0+] RequestApplicationFunctionAuthorization
| 100 || [8.0.0+] RequestApplicationFunctionAuthorization
|-
|-
| 101 || [8.0.0+] RequestApplicationFunctionAuthorizationForSystem
| 101 || [8.0.0+] RequestApplicationFunctionAuthorizationByProcessId
|-
| 102 || [10.0.0+] RequestApplicationFunctionAuthorizationByApplicationId
|-
| 103 || [11.0.0+] RefreshApplicationFunctionBlackListDebugRecord
|-
| 104 || [11.0.0+] RequestApplicationFunctionAuthorizationByProgramId
|-
| 105 || [11.0.0+] GetFunctionBlackListSystemVersionToAuthorize
|-
| 106 || [11.0.0+] GetFunctionBlackListVersion
|-
| 107 || [17.0.0+] RequestApplicationFunctionAuthorizationByApplicationIdAndProgramId
|-
| 108 || [20.0.0+] GetRequiredApplicationVersion
|-
| 1000 || [9.0.0+] LoadNgWordDataForPlatformRegionChina
|-
| 1001 || [9.0.0+] GetNgWordDataSizeForPlatformRegionChina
|}
|}


== RequestSharedFontLoad ==
== RequestLoad ==
Takes a [[#SharedFontType]] (uint32), no output.
Takes a [[#SharedFontType]] (uint32), no output.


== GetSharedFontLoadState ==
== GetLoadState ==
Takes a [[#SharedFontType]] (uint32), returns the [[#LoadState]] (uint32).
Takes a [[#SharedFontType]] (uint32), returns the [[#LoadState]] (uint32).


Line 41: Line 61:
|}
|}


== GetSharedFontSize ==
== GetSize ==
Takes a [[#SharedFontType]] (uint32), returns the Font Size (uint32).
Takes a [[#SharedFontType]] (uint32), returns the Font Size (uint32).


== GetSharedFontAddress ==
== GetSharedMemoryAddressOffset ==
Takes a [[#SharedFontType]] (uint32), returns the offset (uint32) to the Font Address.
Takes a [[#SharedFontType]] (uint32), returns the offset (uint32) to the Font Address.


== GetSharedFontSharedMemoryHandle ==
== GetSharedMemoryNativeHandle ==
No input, returns an output SharedMemory handle.
No input, returns an output SharedMemory handle.


User-processes map this SharedMemory with size=0x1100000 and permissions=R--.
User-processes map this SharedMemory with size=0x1100000 and permissions=R--.


Font data is TTF, located at the offset returned by [[#GetSharedFontAddress]].
Font data is TTF, located at the offset returned by [[#GetSharedMemoryAddressOffset]].


== GetSharedFontInOrderOfPriority ==
== GetSharedFontInOrderOfPriority ==
Line 83: Line 103:
= mii:u, mii:e =
= mii:u, mii:e =
This is "nn::mii::detail::IStaticService".
This is "nn::mii::detail::IStaticService".
These were moved from [[NS_services|ns]] with [3.0.0+].
These are only available when the output from [[Process_Manager_services|pm:bm]] GetBootMode is not Maintenance.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 149: Line 173:
|-
|-
| 25 || [7.0.0+] ConvertCharInfoToCoreData
| 25 || [7.0.0+] ConvertCharInfoToCoreData
|-
| 26 || [10.2.0+] Append
|-
| 27 || [19.0.0-19.0.1] ImportMigrationData
|}
|}


Line 155: Line 183:


This was added with [5.0.0+].
This was added with [5.0.0+].
This is only available when the output from [[Process_Manager_services|pm:bm]] GetBootMode is not Maintenance.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 177: Line 207:
|-
|-
| 17 || DeleteImages
| 17 || DeleteImages
|-
| 18 || [19.0.0+] AddImageForMigration
|-
| 19 || [20.0.0+] ClearHeaderForMigration
|-
| 20 || [20.0.0+] SaveHeaderForMigration
|-
|-
| 100 || DeleteFile
| 100 || DeleteFile
Line 191: Line 227:
= pdm:ntfy =
= pdm:ntfy =
This is "nn::pdm::detail::INotifyService".
This is "nn::pdm::detail::INotifyService".
This was moved from [[NS_services|ns]] with [3.0.0+].
This is only available when the output from [[Process_Manager_services|pm:bm]] GetBootMode is not Maintenance.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 196: Line 236:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 ||  
| 0 || [[#NotifyAppletEvent]]
|-
|-
| 2 ||  
| 2 || [[#NotifyOperationModeChangeEvent]]
|-
|-
| 3 ||  
| 3 || [[#NotifyPowerStateChangeEvent]]
|-
|-
| 4 ||  
| 4 || [[#NotifyClearAllEvent]]
|-
|-
| 5 ||  
| 5 || [2.0.0+] [[#NotifyEventForDebug]]
|-
|-
| 6 || [4.0.0+]
| 6 || [4.0.0+] SuspendUserAccountEventService
|-
|-
| 7 || [4.0.0+]
| 7 || [4.0.0+] ResumeUserAccountEventService
|-
|-
| 8 || [6.0.0+]
| 8 || [6.0.0+]
|-
|-
| 9 || [8.0.0+]
| 9 || [8.0.0+]
|-
| 20 || [20.0.0+]
|-
| 100 || [20.0.0+]
|-
| 101 || [20.0.0+]
|}
|}
== NotifyAppletEvent ==
Takes an input u8 [[#AppletEventType]], an u8 [[Applet_Manager_services#AppletId|AppletId]], an u8 [[Filesystem_services#StorageId|StorageId]], an u8 [[#PlayLogPolicy]], an u32 '''event_x8''', and an u64 '''ProgramId'''. Returns no output.
When [[#PlayLogPolicy]] is 2 ("None") this will immediately return 0.
Logs a new [[#PlayEvent]] with the following data:
* Clears the 0x10-bytes at +0x10.
* u8 +0xF = [[#AppletEventType]].
* Sets the 3 timestamps.
* Converts '''ProgramId''' and writes it to +0x0.
* u32 +0x8 = '''event_x8'''.
* u8 +0xC = [[Applet_Manager_services#AppletId|AppletId]], u8 +0xD = [[Filesystem_services#StorageId|StorageId]], and u8 +0xE = [[#PlayLogPolicy]].
After the initial logging, additional code runs with some of the above input params.
== NotifyOperationModeChangeEvent ==
Takes an input u8 '''inval''', no output.
Logs a new [[#PlayEvent]] with the following data: clears the 0x20-bytes at +0x0, u8 +0x1C = 0x3, u8 +0x0 = '''inval''', and sets the 3 timestamps.
== NotifyPowerStateChangeEvent ==
Takes an input u8 '''inval''', no output.
Logs a new [[#PlayEvent]] with the following data: clears the 0x20-bytes at +0x0, u8 +0x1C = 0x2, u8 +0x0 = '''inval''', and sets the 3 timestamps.
After the initial logging, additional code runs which uses '''inval'''.
== NotifyClearAllEvent ==
No input/output.
== NotifyEventForDebug ==
Takes an input type-0x5 buffer containing an array of [[#PlayEvent]], no output.
Gets the [[System_Settings|system-setting]] <code>pdm!is_production</code>, the size must be 1 and the value must be 0, otherwise an error is returned.
Each [[#PlayEvent]] entry is validated, throwing an error on failure. After an entry is successfully validated, it is written to the log.
== Cmd8 ==
Takes an input u8 [[#AppletEventType]], an u8 [[Applet_Manager_services#LibraryAppletMode|LibraryAppletMode]], an u8 [[Applet_Manager_services#AppletId|AppletId]], an u8 [[Filesystem_services#StorageId|StorageId]], an u8 [[#PlayLogPolicy]], and an u64 '''ProgramId'''. Returns no output.
This is similar to [[#NotifyAppletEvent]].
When [[#PlayLogPolicy]] is 2 ("None") this will immediately return 0.
Logs a new [[#PlayEvent]] with the following data:
* Clears the 0x20-bytes at +0x0.
* u8 +0xF = [[#AppletEventType]].
* Sets the 3 timestamps.
* Converts '''ProgramId''' and writes it to +0x0.
* u8 +0x9 = [[Applet_Manager_services#LibraryAppletMode|LibraryAppletMode]].
* u8 +0x8 = 1.
* u8 +0xC = [[Applet_Manager_services#AppletId|AppletId]], u8 +0xD = [[Filesystem_services#StorageId|StorageId]], and u8 +0xE = [[#PlayLogPolicy]].
After the initial logging, additional code runs with some of the above input params. This is handled the same as [[#NotifyAppletEvent]], except that the value passed for '''event_x8''' is value 0 here.
== Cmd9 ==
Takes an input u8 [[#AppletEventType]], an u8 [[Applet_Manager_services#AppletId|AppletId]], an u8 [[Filesystem_services#StorageId|StorageId]], an 0x20-byte struct, an u8 bool flag, an u8 [[#PlayLogPolicy]], an u32 '''event_x8''', and an u64 '''program_id'''. Returns no output.
[10.0.0+] This now takes an additional input u64, new_program_id. At the very beginning a new func is now called, with params: ({constant value}, &[[#AppletEventType]], &program_id, &new_program_id, &StorageId). Afterwards, where it would originally use program_id, it now uses new_program_id instead. The called func eventually writes the input to a buffer using msgpack, with the output from that being added to a list in state.
This is identical to [[#NotifyAppletEvent]] except for the additional struct/flag params.
After the initial logging, additional code runs with some of the above input params. This is handled the same as [[#NotifyAppletEvent]], except that when the u8 bool flag is set the input struct is used with this.
[10.0.0+] New code at the very end of this func was added. When [[Applet_Manager_services#AppletId|AppletId]] is 0x1, or 0x1F-0x20, the following runs:
* If [[#AppletEventType]] is 1, 5, or 6, func1 is called with param &program_id. This runs msgpack code similar to the above, then does {other things}.
* Otherwise, if [[#AppletEventType]] is 0, func0 is called with param &program_id.
** This calls the same msgpack func at the start as func1. [[Glue_services#GetApplicationLaunchProperty|GetApplicationLaunchProperty]] is used, with the output being copied to state on success, otherwise the output Result is used with other msgpack code.
* If [[#AppletEventType]] doesn't match any of these, nothing is done.


= pdm:qry =
= pdm:qry =
This is "nn::pdm::detail::IQueryService".
This is "nn::pdm::detail::IQueryService".
This was moved from [[NS_services|ns]] with [3.0.0+].
This is only available when the output from [[Process_Manager_services|pm:bm]] GetBootMode is not Maintenance.


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 222: Line 342:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 ||  
| 0 || [[#QueryAppletEvent]] ([1.0.0-7.0.1] QueryApplicationEvent)
|-
| 1 || [1.0.0-6.2.0] [[#QueryPlayStatistics]]
|-
| 2 || [1.0.0-6.2.0] [[#QueryPlayStatisticsByUserAccountId]]
|-
| 3 || [1.0.0-6.2.0] [[#QueryPlayStatisticsByNetworkServiceAccountId]]
|-
| 4 || [[#QueryPlayStatisticsByApplicationId]]
|-
|-
| [1.0.0-6.2.0] 1 ||
| 5 || [[#QueryPlayStatisticsByApplicationIdAndUserAccountId]]
|-
|-
| [1.0.0-6.2.0] 2 ||
| 6 || [1.0.0-6.2.0] [[#QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId]]
|-
|-
| [1.0.0-6.2.0] 3 ||
| 7 || [10.0.0-14.1.2] [[#QueryLastPlayTimeV0]] ([1.0.0-9.2.0] QueryLastPlayTime)
|-
|-
| 4 ||  
| 8 || [[#QueryPlayEvent]]
|-
|-
| 5 ||  
| 9 || [[#GetAvailablePlayEventRange]]
|-
|-
| [1.0.0-6.2.0] 6 ||
| 10 || [3.0.0+] [[#QueryAccountEvent]]
|-
|-
| 7 ||  
| 11 || [4.0.0+] [[#QueryAccountPlayEvent]]
|-
|-
| 8 ||  
| 12 || [4.0.0+] [[#GetAvailableAccountPlayEventRange]]
|-
|-
| 9 ||  
| 13 || [10.0.0-14.1.2] [[#QueryApplicationPlayStatisticsForSystemV0]] ([5.0.0-9.2.0] QueryApplicationPlayStatisticsForSystem)
|-
|-
| 10 ||  
| 14 || [6.0.0-14.1.2] [[#QueryRecentlyPlayedApplication]]
|-
|-
| 11 || [4.0.0+]
| 15 || [6.0.0-14.1.2] [[#GetRecentlyPlayedApplicationUpdateEvent]]
|-
|-
| 12 || [4.0.0+]
| 16 || [10.0.0-14.1.2] [[#QueryApplicationPlayStatisticsByUserAccountIdForSystemV0]] ([6.0.0-9.2.0] QueryApplicationPlayStatisticsByUserAccountIdForSystem)
|-
|-
| 13 || [5.0.0+]
| 17 || [10.0.0+] [[#QueryLastPlayTime]]
|-
|-
| 14 || [6.0.0+]
| 18 || [10.0.0+] [[#QueryApplicationPlayStatisticsForSystem]]
|-
|-
| 15 || [6.0.0+]
| 19 || [10.0.0+] [[#QueryApplicationPlayStatisticsByUserAccountIdForSystem]]
|-
|-
| 16 || [6.0.0+]
| 100 || [20.0.0+]
|-
| 110 || [20.0.0+]
|-
| 118 || [20.0.0+]
|-
| 119 || [20.0.0+]
|}
|}
== QueryAppletEvent ==
Takes ([10.0.0+] an input u8 bool), an input s32 entry_index, a type-0x6 output buffer containing an array of [[#AppletEvent]], and returns an output s32 for actual total output entries.
== QueryPlayStatistics ==
Takes a type-0x6 output buffer containing an array of [[#PlayStatistics]] and returns an output s32 for actual total output entries.
[6.2.0+] This command was removed.
== QueryPlayStatisticsByUserAccountId ==
Takes an input u128 '''Uid''', a type-0x6 output buffer containing an array of [[#PlayStatistics]] and returns an output s32 for actual total output entries.
[6.2.0+] This command was removed.
== QueryPlayStatisticsByNetworkServiceAccountId ==
Takes an input u64 '''NetworkServiceAccountId''', a type-0x6 output buffer containing an array of [[#PlayStatistics]] and returns an output s32 for actual total output entries.
[6.2.0+] This command was removed.
== QueryPlayStatisticsByApplicationId ==
Takes ([10.0.0+] an input u8 bool), an input u64 '''ApplicationId''' and returns an output [[#PlayStatistics]].
== QueryPlayStatisticsByApplicationIdAndUserAccountId ==
Takes ([10.0.0+] an input u8 bool), an input u64 '''ApplicationId''', an input u128 '''Uid''' and returns an output [[#PlayStatistics]].
== QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId ==
Takes an input u64 '''ApplicationId''', an input u64 '''NetworkServiceAccountId''' and returns an output [[#PlayStatistics]].
[6.2.0+] This command was removed.
== QueryLastPlayTimeV0 ==
Takes a type-0x6 output buffer containing an array of [[#LastPlayTime]], and a type-0x5 input buffer containing an array of u64 '''ApplicationId'''. Returns an output s32 for actual total output entries.
[10.0.0+] This now calls the impl func for [[#QueryLastPlayTime]] with flag=0.
== QueryPlayEvent ==
Takes an input s32 entry_index, a type-0x6 output buffer containing an array of [[#PlayEvent]], and returns an output s32 for actual total output entries.
== GetAvailablePlayEventRange ==
No input, returns 3 output s32s: total_entries, start_entry_index, and end_entry_index.
== QueryAccountEvent ==
Takes an input s32 entry_index, a type-0x6 output buffer containing an array of [[#AccountEvent]], and returns an output s32 for actual total output entries.
== QueryAccountPlayEvent ==
Takes an input s32 entry_offset, an input u128 '''Uid''', a type-0x6 output buffer containing an array of [[#AccountPlayEvent]], and returns an output s32 for actual total output entries.
== GetAvailableAccountPlayEventRange ==
Takes an input u128 '''Uid''' and returns 3 output s32s: total_entries, start_entry_index, and end_entry_index.
== QueryApplicationPlayStatisticsForSystemV0 ==
Takes a type-0x6 output buffer containing an array of [[#ApplicationPlayStatistics]] and a type-0x5 input buffer containing an array of u64 '''ApplicationId'''. Returns an output s32 for actual total output entries.
The number of entries in each array is the same.
[10.0.0+] This now calls the impl func for [[#QueryApplicationPlayStatisticsForSystem]] with flag=0.
== QueryRecentlyPlayedApplication ==
Takes ([10.0.0+] an input u8 bool), an input u128 '''Uid''', a type-0x6 output buffer containing an array of u64 '''ApplicationId''', and returns an output s32 for actual total output entries.
Returns a list of applications played by the specified user.
== GetRecentlyPlayedApplicationUpdateEvent ==
No input, returns an output Event handle with autoclear=false.
This is signaled when logging a new [[#PlayEvent]] which would be available via [[#QueryAccountEvent]], where [[#PlayEvent]] +0x18 is 0.
== QueryApplicationPlayStatisticsByUserAccountIdForSystemV0 ==
Takes an [[Account_services#Uid|Uid]], a type-0x6 output buffer containing an array of [[#ApplicationPlayStatistics]] and a type-0x5 input buffer containing an array of u64 '''ApplicationId'''. Returns an output s32 for actual total output entries.
Same as [[#QueryApplicationPlayStatisticsForSystemV0]] except this gets playstats specific to '''Uid'''.
[10.0.0+] This now calls the impl func for [[#QueryApplicationPlayStatisticsByUserAccountIdForSystem]] with flag=0.
== QueryLastPlayTime ==
Takes an input u8 bool, a type-0x6 output buffer containing an array of [[#LastPlayTime]], and a type-0x5 input buffer containing an array of u64 '''ApplicationId'''. Returns an output s32 for actual total output entries.
== QueryApplicationPlayStatisticsForSystem ==
Takes an input u8 bool, a type-0x6 output buffer containing an array of [[#ApplicationPlayStatistics]] and a type-0x5 input buffer containing an array of u64 '''ApplicationId'''. Returns an output s32 for actual total output entries.
The number of entries in each array is the same.
== QueryApplicationPlayStatisticsByUserAccountIdForSystem ==
Takes an input u8 bool, an [[Account_services#Uid|Uid]], a type-0x6 output buffer containing an array of [[#ApplicationPlayStatistics]] and a type-0x5 input buffer containing an array of u64 '''ApplicationId'''. Returns an output s32 for actual total output entries.
Same as [[#QueryApplicationPlayStatisticsForSystem]] except this gets playstats specific to '''Uid'''.


= avm =
= avm =
Line 266: Line 486:
! Cmd || Name
! Cmd || Name
|-
|-
| 100 ||  
| 100 || [[#GetHighestAvailableVersion]]
|-
|-
| 101 ||  
| 101 || [[#GetHighestRequiredVersion]]
|-
|-
| 102 ||  
| 102 || [[#GetVersionListEntry]]
|-
|-
| 103 || No input, returns an [[#IVersionListImporter]].
| 103 || [[#GetVersionListImporter]]
|-
|-
| 200 ||  
| 200 || [[#GetLaunchRequiredVersion]]
|-
|-
| 202 ||  
| 202 || [[#UpgradeLaunchRequiredVersion]]
|-
|-
| 1000 ||  
| 1000 || [[#PushLaunchVersion]]
|-
|-
| 1001 ||  
| 1001 || [[#ListVersionList]]
|-
|-
| 1002 ||  
| 1002 || [[#ListRequiredVersion]]
|}
|}
=== GetHighestAvailableVersion ===
Takes two u64 title ids. Returns the highest available version of both.
Unused by official software.
=== GetHighestRequiredVersion ===
Takes two u64 title ids. Returns the highest available version of both.
Official software calls this with the id of an application and its update.
=== GetVersionListEntry ===
Takes an input u64 title id. Returns associated [[#VersionListEntry]].
=== GetVersionListImporter ===
No input, returns an [[#IVersionListImporter]].
=== GetLaunchRequiredVersion ===
Takes an input u64 title id. Return the required launch version.
=== UpgradeLaunchRequiredVersion ===
Takes a u32 launch version and a u64 title id.
Version has to be greater the result of GetLaunchRequiredVersion.
=== PushLaunchVersion ===
Takes a u32 launch version and a u64 title id.
=== ListVersionList ===
No input, returns a type 6 buffer of [[#VersionListEntry]] and a u32 count.
=== ListRequiredVersion ===
No input, returns a type 6 buffer of [[#RequiredVersionEntry]] and a u32 count.


== IVersionListImporter ==
== IVersionListImporter ==
Line 294: Line 547:
! Cmd || Name
! Cmd || Name
|-
|-
| 0 ||  
| 0 || [[#SetTimestamp]]
|-
| 1 || [[#PushEntries]]
|-
| 2 || [[#Flush]]
|}
 
=== SetTimestamp ===
Takes an input u64 unix timestamp, no output.
 
=== PushEntries ===
Takes an input type-6 buffer [[#VersionListEntry]], no output.
 
=== Flush ===
No input, no output. Flushed the commited data to its safe.
 
= VersionListEntry =
This is a 0x10-byte struct.
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || Update Id.
|-
| 0x8 || 0x4 || Available version.
|-
| 0xC || 0x4 || Required version.
|}
 
= RequiredVersionEntry =
This is a 0x10-byte struct.
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || Id.
|-
| 0x8 || 0x4 || Required version.
|-
| 0xC || 0x4 || Padding.
|}
 
= AppletEvent =
This is "nn::pdm::AppletEvent" ([1.0.0-7.0.1] "nn::pdm::ApplicationEvent").
 
This is a 0x28-byte ([1.0.0-15.0.1] 0x18-byte) struct.
 
Pre-16.0.0:
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || ProgramId
|-
| 0x8 || 0x4 || entryindex
|-
| 0xC || 0x4 || timestamp0
|-
| 0x10 || 0x4 || timestamp1
|-
| 0x14 || 0x1 || [[#PlayEvent]] +0xF
|-
| 0x15 || 0x3 || Padding
|}
 
Timestamp format, converted from PosixTime: total minutes since epoch UTC 1999/12/31 00:00.
 
[16.0.0+]:
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || ProgramId
|-
| 0x8 || 0x4 || entryindex
|-
| 0xC || 0x4 || Padding
|-
| 0x10 || 0x8 || timestamp0 in PosixTime
|-
| 0x18 || 0x8 || timestamp1 in PosixTime
|-
| 0x20 || 0x1 || [[#PlayEvent]] +0xF
|-
| 0x21 || 0x7 || Padding
|}
 
= PlayStatistics =
This is "nn::pdm::PlayStatistics".
 
This is a 0x48-byte ([1.0.0-15.0.1] 0x28-byte) struct.
 
Pre-16.0.0:
 
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || ProgramId
|-
| 0x8 || 0x4 || First entryindex
|-
| 0xC || 0x4 || First timestamp0. Same as the first [[#AppletEvent]] timestamp.
|-
|-
| 1 ||  
| 0x10 || 0x4 || First timestamp1. Same as the second [[#AppletEvent]] timestamp.
|-
|-
| 2 ||  
| 0x14 || 0x4 || Last entryindex
|-
| 0x18 || 0x4 || Last timestamp0. Same as the first [[#AppletEvent]] timestamp.
|-
| 0x1C || 0x4 || Last timestamp1. Same as the second [[#AppletEvent]] timestamp.
|-
| 0x20 || 0x4 || Total play-time in minutes.
|-
| 0x24 || 0x4 || Total times the program was launched.
|}
|}
[16.0.0+]:
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || ProgramId
|-
| 0x8 || 0x4 || First entryindex
|-
| 0xC || 0x4 || Padding
|-
| 0x10 || 0x8 || First timestamp0. Same as the first [[#AppletEvent]] timestamp except in PosixTime.
|-
| 0x18 || 0x8 || First timestamp1. Same as the second [[#AppletEvent]] timestamp except in PosixTime.
|-
| 0x20 || 0x4 || Last entryindex
|-
| 0x24 || 0x4 || Padding
|-
| 0x28 || 0x8 || Last timestamp0. Same as the first [[#AppletEvent]] timestamp except in PosixTime.
|-
| 0x30 || 0x8 || Last timestamp1. Same as the second [[#AppletEvent]] timestamp except in PosixTime.
|-
| 0x38 || 0x8 || Total play-time in nanoseconds.
|-
| 0x40 || 0x4 || Total times the program was launched.
|-
| 0x44 || 0x4 || Padding
|}
= LastPlayTime =
This is "nn::pdm::LastPlayTime".
This is a 0x18-byte struct and contains data from the last time the program was played.
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || ApplicationId
|-
| 0x8 || 0x4 || Same as the first [[#AppletEvent]] timestamp.
|-
| 0xC || 0x4 || Same as the second [[#AppletEvent]] timestamp.
|-
| 0x10 || 0x4 || Total minutes since the program was last played.
|-
| 0x14 || 0x1 || Flag indicating whether the above field is set.
|-
| 0x15 || 0x3 || Padding
|}
= PlayEventType =
This is an enum for [[#PlayEvent]] +0x1C, which indicates the type of [[#PlayEvent]].
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || Applet
|-
| 1 || Account
|-
| 2 || PowerStateChange
|-
| 3 || OperationModeChange
|-
| 4 || Initialize. Used for the very first [[#PlayEvent]] entry in the log.
|}
= AppletEventType =
This is an enum for [[#PlayEvent]] +0xF with [[#PlayEventType]] = Applet, this indicates the type of the Applet event.
{| class="wikitable" border="1"
|-
! Value
! Description
|-
| 0 || "launch"
|-
| 1 || "exit"
|-
| 2 || "in_focus"
|-
| 3 || "out_of_focus"
|-
| 4 || "out_of_focus"
|-
| 5 || "exit"
|-
| 6 || "exit"
|}
= PlayLogPolicy =
{| class="wikitable" border="1"
|-
! Value
! Meaning
! Description
|-
| 0 || All || All pdm:qry cmds which require [[#PlayEventType]] = Applet and AppletId = Application will only return the entry when PlayLogPolicy matches this value.
|-
| 1 || LogOnly || The above commands will filter out the entry with this.
|-
| 2 || None || pdm:ntfy [[#NotifyAppletEvent]], [[#Cmd8]], and [[#Cmd9]] will immediately return 0 when the input param matches this value.
|-
| 3 || || [10.0.0+] The cmds which require PlayLogPolicy == All, now also allow value 3 if the cmd input flag is set.
|}
This is an enum for [[#PlayEvent]] +0xE with [[#PlayEventType]] = Applet. This is set via the above commands, which uses this as an input param.
= PlayEvent =
This is "nn::pdm::PlayEvent".
This is a 0x38-byte struct and is the raw entry struct directly read from FS, without any entry filtering. The other structs are extracted+converted from this one, with filtering.
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x1C || 0x1 || [[#PlayEventType]]
|-
| 0x1D || 0x3 || Padding
|-
| 0x20 || 0x8 || PosixTime timestamp from [[PCV_services|StandardUserSystemClock]].
|-
| 0x28 || 0x8 || PosixTime timestamp from [[PCV_services|StandardNetworkSystemClock]].
|-
| 0x30 || 0x8 || Timestamp in seconds derived from [[PCV_services|StandardSteadyClock]].
|}
Filtering:
* [[#QueryAppletEvent]], [[#QueryLastPlayTime]], and [[#QueryApplicationPlayStatisticsForSystem]]: PlayEvent +0x1C must be 0, and [[#PlayLogPolicy]] must be 0. [10.0.0+] These will also allow [[#PlayLogPolicy]] value 3, if the input flag is set.
** With [[#QueryLastPlayTime]]/[[#QueryApplicationPlayStatisticsForSystem]] the [[Applet_Manager_services#AppletId|AppletId]] must be 1. [10.0.0+] These now also allow [[Applet_Manager_services#AppletId|AppletId]] 0x1F/0x20.
* [[#QueryPlayStatisticsByApplicationId]]: PlayEvent +0x1C must be 0, +0xC must be 1 ([10.0.0+] or 0x1F/0x20), and the ProgramId must match. [10.0.0+] [[#PlayLogPolicy]] must be 0. Value 3 is allowed if the input flag is set.
* [[#QueryAccountEvent]]: PlayEvent +0x1C must be 1 and PlayEvent +0x18 must be <=1.
* [[#QueryApplicationPlayStatisticsForSystem]]: In addition to the above, this also handles [[#PlayEventType]] PowerStateChange, where PlayEvent +0x0 is value 0 or 1.
The structure of the first 0x1C-bytes are determined by [[#PlayEventType]]. For ProgramIds/userIDs, the low/high u32 in each u64 is swapped.
Applet:
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || ProgramId
|-
| 0x8 || 0x4 || Title version, set by pdm:ntfy [[#NotifyAppletEvent]] and [[#Cmd9]].
|-
| 0x8 || 0x1 || When set to u8 0x1 by pdm:ntfy [[#Cmd8]], this indicates that +0x9 is set. Only used for non-applications.
|-
| 0x9 || 0x1 || See above. [[Applet_Manager_services#LibraryAppletMode|LibraryAppletMode]]
|-
| 0xC || 0x1 || [[Applet_Manager_services#AppletId|AppletId]]
|-
| 0xD || 0x1 || [[Filesystem_services#StorageId|StorageId]]
|-
| 0xE || 0x1 || [[#PlayLogPolicy]]
|-
| 0xF || 0x1 || [[#AppletEventType]]
|-
| 0x10 || 0xC || Unused
|}
Account:
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x10 || userID
|-
| 0x10 || 0x8 || ProgramId, when u8 +0x18 = 2.
|-
| 0x18 || 0x1 || Type. 0-1 to be listed by [[#QueryAccountEvent]], or 2 to include the above ProgramId.
|-
| 0x19 || 0x3 || Padding
|}
PlayEventType PowerStateChange/OperationModeChange: u8 +0x0 is the input value from [[#NotifyOperationModeChangeEvent]]/[[#NotifyPowerStateChangeEvent]], the rest is unused.
= AccountEvent =
This is "nn::pdm::AccountEvent".
This is a 0x38-byte ([10.0.0-15.0.1] 0x40-byte [3.0.0-9.2.0] 0x38-byte) struct.
This was added with [3.0.0+].
[3.0.0-9.2.0]:
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x10 || userID
|-
| 0x10 || 0x4 || entryindex
|-
| 0x14 || 0x4 || Padding
|-
| 0x18 || 0x8 || [[#PlayEvent]] +0x20
|-
| 0x20 || 0x8 || [[#PlayEvent]] +0x28
|-
| 0x28 || 0x8 || [[#PlayEvent]] +0x30
|-
| 0x30 || 0x1 || [[#PlayEvent]] +0x18
|-
| 0x31 || 0x7 || Padding
|}
[10.0.0-15.0.1]:
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x10 || userID
|-
| 0x10 || 0x8 || ProgramId
|-
| 0x18 || 0x4 || entryindex
|-
| 0x1C || 0x4 || Padding
|-
| 0x20 || 0x8 || [[#PlayEvent]] +0x20
|-
| 0x28 || 0x8 || [[#PlayEvent]] +0x28
|-
| 0x30 || 0x8 || [[#PlayEvent]] +0x30
|-
| 0x38 || 0x1 || [[#PlayEvent]] +0x18
|-
| 0x39 || 0x7 || Padding
|}
[16.0.0+]:
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x10 || userID
|-
| 0x10 || 0x8 || ProgramId
|-
| 0x18 || 0x4 || entryindex
|-
| 0x1C || 0x4 || Padding
|-
| 0x20 || 0x8 || [[#PlayEvent]] +0x20
|-
| 0x28 || 0x8 || [[#PlayEvent]] +0x28
|-
| 0x30 || 0x1 || [[#PlayEvent]] +0x18
|-
| 0x31 || 0x7 || Padding
|}
= AccountPlayEvent =
This is "nn::pdm::AccountPlayEvent".
This is a 0x28-byte struct and is the raw entry struct directly read from FS, without any entry filtering. This is separate from [[#PlayEvent]].
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x4 || ?
|-
| 0x4 || 0x8 || ProgramId, with the u32 low/high words swapped.
|-
| 0xC || 0xC || ?
|-
| 0x18 || 0x8 || POSIX timestamp
|-
| 0x20 || 0x8 || POSIX timestamp
|}
= ApplicationPlayStatistics =
This is "nn::pdm::ApplicationPlayStatistics".
This is a 0x18-byte struct.
{| class="wikitable" border="1"
|-
! Offset
! Size
! Description
|-
| 0x0 || 0x8 || ApplicationId
|-
| 0x8 || 0x8 || Total play-time in nanoseconds.
|-
| 0x10 || 0x8 || Total times the program was launched.
|}
= Notes =
Various services are only available depending on the output of [[Process_Manager_services|pm:bm]] GetBootMode, see above.
The func which initializes pl:* services calls a func, which then uses [[Process_Manager_services|pm:bm]] GetBootMode. This checks for BootMode Normal - the functionality here has no affect on whether pl:* services are available however.


[[Category:Services]]
[[Category:Services]]