Files
AnyPS5/docs/dev/debt/libSceNpUniversalDataSystem.md
T
Yunus Shaikh 4362803457 feat(libSceNpUniversalDataSystem): unlock trophies through the title's statistics
Events other than the trophy events go through the title's
sce_sys/uds/udsNN.ucp: stats_definition.json gives the statistics that
keep their latest uint32 or uint64 value, and stats_extraction.json the
event property ($.name, dotted for nested objects) that sets each one.
Statistics are kept per user and service label in
_trophy/<user id>_<service label>.stats.txt next to the unlocks.

After each event that sets a statistic, every trophy's unlockCondition
(ge, gt, le or lt against its targetValue) is checked on the values that
event set and the stored values of the other statistics, so a later
event setting the same statistic cannot hide what this one reached.
Reached trophies unlock through the same path as _UnlockTrophy.
Progressive trophies report their statistic as progress, and
APS5_TRACE_UDS prints each statistic an event sets. A missing udsNN.ucp
is ignored and a malformed one is logged once.
2026-10-17 23:28:56 +00:00

2.6 KiB

libSceNpUniversalDataSystem technical debt

Unknown function info

  • Events: sceNpUniversalDataSystemCreateEvent copies prop and returns the event's own property object through prop_ptr, as KytyPS5 does; sceNpUniversalDataSystemEventPropertyObjectSetObject, SetArray and the array setters for objects and arrays store a copy of value and return the stored copy through value_ptr. Destroying a property object or array that its Create function did not return (an event's property object or a stored copy) does nothing, as its owner frees it. These ownership rules are not verified on a console, nor are the output of sceNpUniversalDataSystemEventToString (still {}) and sceNpUniversalDataSystemEventEstimateSize (still 3).

Functional

  • Trophy events: sceNpUniversalDataSystemPostEvent stores an _UnlockTrophy event with an int32 _trophy_id of 0 or more as an unlock for the user and service label of its context, as KytyPS5 does. _UpdateTrophyProgress, named only by a third-party unlocker, is logged once per trophy and not interpreted. A context need not be registered, and every post of an event that sceNpUniversalDataSystemCreateEvent returned and that is not yet destroyed returns success (a null or any other event pointer stops the game): KytyPS5's errors for an unknown or unregistered context and for a malformed unlock are not verified. The storage statistics stay zero.
  • Statistics: every other event goes through the title's rules in sce_sys/uds/udsNN.ucp, which libSceNpTrophy2 reads. Only statistics with "aggregation":"latest" and dataType uint32 or uint64 are kept, as in KytyPS5; no public source documents the other aggregations or types, so their definitions and rules are skipped. Only rules whose condition is an eventName alone and whose input is a $.name path (dotted for nested objects) are applied. A value is used when it is an integer of any width that is not negative and fits the statistic's type and minValue/maxValue; KytyPS5 requires the statistic's exact width, and whether the console converts, clamps or rejects other values is not known. Statistics are stored per user and service label, and every trophy's unlockCondition is compared after each event that sets one.