Real Time Clock.
Module
Version |
World |
Privilege
|
0.931.010-3.740.011 |
Non-secure |
Kernel
|
Libraries
Known NIDs
Version |
Name |
World |
Visibility |
NID
|
0.920-3.740.011 |
SceRtcForDriver |
Non-secure |
Kernel |
0x0351D827
|
0.931.010-3.740.011 |
SceRtc |
Non-secure |
User |
0x3503487E
|
Types
typedef struct SceRtcTickBase { // size is 0x28-bytes
SceRtcTick tick_src_0;
SceRtcTick tick_dst_0;
int unk_0x10;
int unk_0x14;
int tick_flags_0;
int unk_0x1C;
int unk_0x20;
int unk_0x24;
} SceRtcTickBase;
// internal use. From SceRtc_data + 0x38
typedef struct SceRtcTickContext { // size is 0x140-bytes
SceRtcTickBase current_secure_tick;
SceRtcTickBase current_retained_network_tick;
SceRtcTickBase current_tool_secure_tick;
SceRtcTickBase current_gps_tick;
SceRtcTickBase current_debug_network_tick;
SceRtcTickBase unk_tick_5;
SceRtcTickBase unk_tick_6;
SceRtcTickBase unk_tick_7;
} SceRtcTickContext;
Rtc Tick
The Rtc Tick is a 64-bit integer that corresponds to the number of microseconds since 1/01/01 00:00:00.000000. A tick can be considered as the smallest unit of time usually used by PS Vita operating system and softwares.
Below are examples of Rtc Tick values and their human-readable "date-time" equivalent.
Rtc Tick |
DateTime
|
0x0000000000000000 |
1/01/01 00:00:00.000000
|
0x0000000000000001 |
1/01/01 00:00:00.000001
|
0x00000000000F4240 |
1/01/01 00:00:01.000000
|
0x0000000003938700 |
1/01/01 00:01:00.000000
|
0x00000000D693A400 |
1/01/01 01:00:00.000000
|
0x000000141DD76000 |
1/01/02 00:00:00.000000
|
0x00DCBFFEFF2BC000 |
1970/01/01 00:00:00.000000
|
0x00E2156879BFC000 |
2017/07/29 00:00:00.000000
|
0x00E2CDD60F4CE000 |
2024/01/01 00:00:00.000000
|
0x8000000000000000 |
30134/01/10 04:00:54.775808
|
0xFFFFFFFFFFFFFFFF |
60267/01/19 08:01:49.551615
|
To convert a DateTime to a Rtc Tick, one can use the following approximate calculation.
#define RTC_SECOND (1 * 1000 * 1000)
#define RTC_MIN (60ull * RTC_SECOND)
#define RTC_HOUR (60ull * RTC_MIN)
#define RTC_DAY (24ull * RTC_HOUR)
#define RTC_YEAR (365ull * RTC_DAY)
rtc_tick = year * RTC_YEAR + day * RTC_DAY + hour * RTC_HOUR + min * RTC_MIN + second * RTC_SECOND + usec;
However, when you convert 1970/01/01 00:00:00.000000 to a Rtc Tick using this calculation, the result is 0xDCB731F0F1C000 (1969/09/11 00:00:00.000000), which is different from the result shown in some of the actual Rtc Tick examples.
// 0x00DCBFFEFF2BC000 - 0xDCB731F0F1C000 = 9676800000000 (just 112 day)
Up to this point, we have been doing simple calculations, but to accurately convert from DateTime to Rtc Tick, we need to take leap years into account. There were 478 leap years between 1/01/01 00:00:00.000000 and 1970/01/01 00:00:00.000000, but that not match the difference.
Therefore, to convert from DateTime to the correct Rtc Tick, the following complex calculation must be performed. Note that there is no proof yet that this calculation can convert to the correct Rtc Tick.
#define RTC_SECOND (1 * 1000 * 1000)
#define RTC_MIN (60ull * RTC_SECOND)
#define RTC_HOUR (60ull * RTC_MIN)
#define RTC_DAY (24ull * RTC_HOUR)
#define RTC_YEAR (365ull * RTC_DAY)
int datetime2tick(SceRtcTick *pTick, SceUInt32 year, SceUInt32 month, SceUInt32 day, SceUInt32 hour, SceUInt32 min, SceUInt32 second, SceUInt32 usec){
pTick->tick = 0ull;
SceBool target_year_is_leap = SCE_FALSE;
SceUInt32 leap_count = 0;
if ((year % 400) == 0 || ((year % 4) == 0 && (year % 100) != 0))
target_year_is_leap = SCE_TRUE;
for (int i=0; i<(year - 1); i++) {
if ((i % 400) == 0 || ((i % 4) == 0 && (i % 100) != 0))
leap_count = leap_count + 1;
}
SceUInt64 year_diff = leap_count / 365;
SceUInt64 day_diff = leap_count % 365;
day_diff -= target_year_is_leap;
pTick->tick = (SceUInt64)(year - 1) * RTC_YEAR + year_diff * RTC_YEAR + day_diff * RTC_DAY;
for (int i=0; i<(month-1); i++)
pTick->tick += g_month_list[target_year_is_leap * 12 + i] * RTC_DAY;
pTick->tick += (day - 1) * RTC_DAY;
pTick->tick += hour * RTC_HOUR;
pTick->tick += min * RTC_MIN;
pTick->tick += second * RTC_SECOND;
pTick->tick += usec;
return 0;
}
SceRtc Time Reversal Security
If some Rtc ticks in memory are lower than the constant set in SceRtc, those ticks are set to 0.
The Rtc tick constants vary per System Software version as they are updated with some System Software updates containing a newer SceRtc kernel module.
System Software Version |
SceRtc Hardcoded Date
|
< 1.00 |
?
|
1.00 - 1.67 ?1.692? |
2011/08/01
|
1.80 - 1.81 |
2012/06/01
|
2.00 - 2.61 |
2012/09/01
|
2.50 - 3.00 |
2013/01/01
|
3.30 - 3.36 |
2014/01/01
|
3.500.000 - 3.740.011 |
2015/01/01
|
SceRtcForDriver
Some RTC functions apparently not present on PS Vita even on 3.200.010 but present on PSP:
sceRtcTickAddMonths
sceRtcTickAddYears
sceRtcCompareTickForDriver
Version |
NID
|
0.920-3.740.011 |
0x0EBB3F12
|
Returns 0 if tick_1 == tick_2, -1 if tick_1 < tick_2 and 1 else.
int sceRtcCompareTickForDriver(const SceRtcTick *tick_1, const SceRtcTick *tick_2);
sceRtcConvertLocalTimeToUtcForDriver
Version |
NID
|
3.60 |
0xAD2F3544
|
sceRtcConvertUtcToLocalTimeForDriver
Version |
NID
|
3.60 |
0xC6E03DD4
|
sceRtcFormatRFC2822ForDriver
Version |
NID
|
3.60 |
0xBA3415F8
|
sceRtcFormatRFC2822LocalTimeForDriver
Version |
NID
|
3.60 |
0x1F7FC209
|
sceRtcFormatRFC3339ForDriver
Version |
NID
|
3.60 |
0xD32AC698
|
int sceRtcFormatRFC3339ForDriver(char *pszDateTime, const SceRtcTick *utc, int iTimeZoneMinutes);
sceRtcFormatRFC3339LocalTimeForDriver
Version |
NID
|
3.60 |
0x35925318
|
sceRtcGetAccumulativeTimeForDriver
Version |
NID
|
3.60 |
0x0A86FB04
|
Also present in PSP under the official names sceRtcGetAccumulativeTime and sceRtcGetAccumlativeTime.
SceULong64 sceRtcGetAccumulativeTimeForDriver(void);
sceRtcGetAlarmTickForDriver
Version |
NID
|
3.60 |
0xC838275A
|
sceRtcGetCurrentAdNetworkTickForDriver
Version |
NID
|
3.60 |
0x3E3C09A0
|
sceRtcGetCurrentClockForDriver
Version |
NID
|
3.60 |
0xA930CD1A
|
sceRtcGetCurrentClockLocalTimeForDriver
Version |
NID
|
3.60 |
0x7DC0DF93
|
sceRtcGetCurrentDebugNetworkTickForDriver
Version |
NID
|
3.60 |
0xC141632A
|
sceRtcGetCurrentGpsTickForDriver
Version |
NID
|
3.60 |
0xF69B610F
|
sceRtcGetCurrentNetworkTickForDriver
Version |
NID
|
3.60 |
0xF1517B38
|
If the current NetworkTick is less than 2015/01/01, the system will ignore the registry setting and update the NetworkTick from the internet.
int sceRtcGetCurrentNetworkTickForDriver(SceRtcTick *tick);
sceRtcGetCurrentRetainedNetworkTickForDriver
Version |
NID
|
3.60 |
0x40B4BCFF
|
sceRtcGetCurrentTickForDriver
Version |
NID
|
3.60 |
0xDEC408D4
|
sceRtcGetCurrentSecureTickForDriver
Version |
NID
|
1.03-3.60 |
0x401C0954
|
If the current SecureTick is less than 2015/01/01, it sets 0xDDDEF8B3A14000(1980/01/01 00:00:00 UTC) to the Secure Tick and returns error code 0x80251002.
int sceRtcGetCurrentSecureTickForDriver(SceRtcTick *tick);
sceRtcTickAddTicksForDriver
Version |
NID
|
0.931.010-3.600.011 |
0xCE51C2A1
|
Adds time (in ticks) to a Rtc tick structure.
int sceRtcTickAddTicksForDriver(SceRtcTick *pDst, const SceRtcTick *pSrc, SceUInt64 num_ticks);
sceRtcTickAddMicrosecondsForDriver
Version |
NID
|
3.200.010 |
0xA82AC5B3
|
Adds time (in microseconds) to a time structure (in nanosecond).
int sceRtcTickAddMicrosecondsForDriver(SceRtcTick *pDst, const SceRtcTick *pSrc, SceUInt64 microseconds);
sceRtcTickAddSecondsForDriver
Version |
NID
|
0.931.010-3.600.011 |
0x9C8AF264
|
Adds time (in second) to a time structure (in nanosecond).
int sceRtcTickAddSecondsForDriver(SceRtcTick *pDst, const SceRtcTick *pSrc, SceUInt64 seconds);
sceRtcTickAddMinutesForDriver
Version |
NID
|
3.60 |
0x0F9E02EF
|
int sceRtcTickAddMinutesForDriver(SceRtcTick *pDst, const SceRtcTick *pSrc, SceUInt64 seconds);
sceRtcTickAddHoursForDriver
Version |
NID
|
3.200.010 |
0x32E50C36
|
int sceRtcTickAddHoursForDriver(SceRtcTick *pDst, const SceRtcTick *pSrc, SceUInt32 hours);
sceRtcTickAddDaysForDriver
Version |
NID
|
3.60 |
0x0CB72FAF
|
Used by SceCompat#sceCompatSetUpdateState.
int sceRtcTickAddDaysForDriver(SceRtcTick *pDst, const SceRtcTick *pSrc, SceUInt32 days);
sceRtcTickAddWeeksForDriver
Version |
NID
|
3.200.010 |
0x24209FBF
|
int sceRtcTickAddWeeksForDriver(SceRtcTick *pDst, const SceRtcTick *pSrc, SceUInt32 weeks);
sceRtcConvertDateTimeToTickForDriver
Version |
NID
|
0.990.000-3.740.011 |
0xF139E359
|
This is a guessed name. This may be the reciprocal function of #sceRtcConvertTickToDateTimeForDriver.
int sceRtcConvertDateTimeToTickForDriver(const SceDateTime *dateTime, SceRtcTick *pTick);
sceRtcConvertTickToDateTimeForDriver
Version |
NID
|
1.03-3.60 |
0x42A0DFCB
|
This is a guessed name. This may be the reciprocal function of #sceRtcConvertDateTimeToTickForDriver.
Used with the result of #sceRtcGetCurrentSecureTickForDriver. Used by SceCoredump, SceSblGcAuthMgr.
int sceRtcConvertTickToDateTimeForDriver(SceDateTime *pDateTime, const SceRtcTick *tick);
sceRtcConvertDateTimeToUnixTimeForDriver
Version |
NID
|
3.60 |
0x497B5DC9
|
This is a guessed name. This may be the reciprocal function of #sceRtcConvertUnixTimeToDateTimeForDriver.
Used by SceCoredump.
int sceRtcConvertDateTimeToUnixTimeForDriver(const SceDateTime *dateTime, SceUInt64 *pMicroseconds);
sceRtcConvertUnixTimeToDateTimeForDriver
Version |
NID
|
3.60 |
0xDE9F4515
|
This is a guessed name. This may be the reciprocal function of #sceRtcConvertDateTimeToUnixTimeForDriver.
This function does: microseconds * 1000000 + 0xdcbffeff2bc000
. 0xdcbffeff2bc000
represents UNIX time i.e. the date 1970/01/01 00:00:00.000000. The microseconds is multiplied by 1000000 to convert from microseconds to seconds.
int sceRtcConvertUnixTimeToDateTimeForDriver(SceDateTime *pDateTime, const SceUInt32 microseconds);
sceRtcConvertDateTimeToFatTimeForDriver
Version |
NID
|
3.200.010 |
0x09AF419B
|
This is a guessed name. Official name may be sceRtcFormatRFC3339LocalTimeForDriver (see PSP sceRtc).
int sceRtcConvertDateTimeToFatTimeForDriver(const SceDateTime *pDateTime, SceUInt32 *pFatTime);
sceRtcSetCurrentAuxTickForDriver
Version |
NID
|
0.990.000-3.740.011 |
0xA7236656
|
int sceRtcSetCurrentAuxTickForDriver(SceRtcTick *tick);
sceRtcGetLastAdjustedTickForDriver
Version |
NID
|
3.60 |
0x8A987573
|
sceRtcGetLastReincarnatedTickForDriver
Version |
NID
|
3.60 |
0x3D614A9A
|
sceRtcGetSecureAlarmTickForDriver
Version |
NID
|
3.60 |
0xBD53731C
|
sceRtcSynchronizeForDriver
Version |
NID
|
3.60-3.74 |
0xA2D280B4
|
Initializes SceRtc internal flags.
int sceRtcSynchronizeForDriver(void);
SceRtcForDriver_ABA035B7
Version |
NID
|
3.60 |
0xABA035B7
|
Reset all SceRtc internal flags to 0.
Returns 0.
int SceRtcForDriver_ABA035B7(void);
sceRtcGetCurrentToolSecureTickForDriver
Version |
NID
|
0.990-3.60 |
0xA0D7899A
|
This is a guessed name.
Used on Tool only. Used when checking DevKit activation license expire date.
Creates a tick using SceKernelThreadMgr#sceKernelGetSystemTimeWideForDriver.
int sceRtcGetCurrentToolSecureTickForDriver(SceRtcTick *pTick);
sceRtcIsAlarmedForDriver
Version |
NID
|
3.60 |
0xCD295F0C
|
sceRtcIsSecureAlarmedForDriver
Version |
NID
|
3.60 |
0xE39F2ABE
|
sceRtcRegisterCallbackForDriver
Version |
NID
|
3.60 |
0x5220870D
|
sceRtcRegisterSecureAlarmCallbackForDriver
Version |
NID
|
3.60 |
0xCF84DFC0
|
sceRtcSetAlarmTickForDriver
Version |
NID
|
3.60 |
0xD610C646
|
sceRtcSetConfForDriver
Version |
NID
|
3.60 |
0xACFE5A9F
|
sceRtcSetCurrentDebugNetworkTickForDriver
Version |
NID
|
3.60 |
0xAAB6053F
|
sceRtcSetCurrentNetworkTickForDriver
Version |
NID
|
3.60 |
0x162E486E
|
sceRtcSetCurrentSecureTickForDriver
Version |
NID
|
3.60 |
0x7D431C87
|
sceRtcSetCurrentTickForDriver
Version |
NID
|
3.60 |
0x70A78CD2
|
sceRtcSetSecureAlarmTickForDriver
Version |
NID
|
3.60 |
0x8333790D
|
sceRtcUnregisterCallbackForDriver
Version |
NID
|
3.60 |
0x9546C68B
|
sceRtcUnregisterSecureAlarmCallbackForDriver
Version |
NID
|
3.60 |
0xEDDC2325
|
SceRtcForDriver_FFD7A04F
Version |
NID
|
3.60 |
0xFFD7A04F
|
Used indirectly by SceProcessmgr#sceKernelLibcTime.
SceRtcForDriver_9097EF0D
Version |
NID
|
3.60 |
0x9097EF0D
|
Used indirectly by SceProcessmgr.
sceRtcGetDayOfWeekForDriver
Version |
NID
|
3.60 |
0x0F800878
|
Used indirectly by SceProcessmgr.
int sceRtcGetDayOfWeekForDriver(SceUInt32 year, SceUInt32 month, SceUInt32 day)
sceRtcCheckValidForDriver
Version |
NID
|
3.200.010 |
0xADF63D7C
|
int sceRtcCheckValidForDriver(const SceDateTime *pDateTime);
sceRtcGetOneSecondForDriver
Version |
NID
|
3.200.010 |
0x6965E5DF
|
This is a guessed name.
SceUInt32 sceRtcGetOneSecondForDriver(void);
sceRtcIsLeapYearForDriver
Version |
NID
|
3.200.010 |
0x6F96FAA5
|
SceBool sceRtcIsLeapYearForDriver(SceUInt32 year);
SceRtcForDriver_A1F41AE2
Version |
NID
|
3.200.010 |
0xA1F41AE2
|
Official name may be either sceRtcGetWin32FileTime (see PSP sceRtc).
int SceRtcForDriver_A1F41AE2(SceRtcTick *pTick, const char *str);
SceRtcForDriver_BA14600F
Version |
NID
|
3.200.010 |
0xBA14600F
|
Official name may be sceRtcSetWin32FileTime (see PSP sceRtc).
It may be related to FILETIME on Windows.
int SceRtcForDriver_BA14600F(SceRtcTick *pDst, SceUInt64 a2);
sceRtcGetDaysInMonthForDriver
Version |
NID
|
3.200.010 |
0xC2DC38D9
|
Retrieves the number of days in the month of a specific year.
For example, in February 1970 there were 28 days versus 29 days in February 1972.
int sceRtcGetDaysInMonthForDriver(SceUInt32 year, SceUInt32 month);
SceRtc
_sceRtcGetCurrentNetworkTick
Version |
NID
|
1.69-3.60 |
0x06F734FE
|
_sceRtcConvertLocalTimeToUtc
Version |
NID
|
1.69-3.60 |
0x0FC8AC41
|
_sceRtcConvertUtcToLocalTime
Version |
NID
|
1.69-3.60 |
0x1E61DDA4
|
_sceRtcGetCurrentTick
Version |
NID
|
1.69-3.60 |
0x247EE33B
|
_sceRtcGetCurrentClock
Version |
NID
|
1.69-3.60 |
0x24947354
|
sceRtcGetAccumulativeTime
Version |
NID
|
1.69-3.60 |
0x258BE8EC
|
Also present in PSP under the official names sceRtcGetAccumulativeTime and sceRtcGetAccumlativeTime.
SceULong64 sceRtcGetAccumulativeTime(void);
_sceRtcFormatRFC2822
Version |
NID
|
1.69-3.60 |
0x2CD6AC86
|
_sceRtcGetCurrentGpsTick
Version |
NID
|
1.69-3.60 |
0x3BA820E5
|
_sceRtcGetCurrentClockLocalTime
Version |
NID
|
1.69-3.60 |
0x41A6C861
|
_sceRtcFormatRFC3339LocalTime
Version |
NID
|
1.69-3.60 |
0x4836474D
|
_sceRtcFormatRFC2822LocalTime
Version |
NID
|
1.69-3.60 |
0x4C7ED349
|
_sceRtcFormatRFC3339
Version |
NID
|
1.69-3.60 |
0x7EE2CBEF
|
_sceRtcGetCurrentRetainedNetworkTick
Version |
NID
|
1.69-3.60 |
0xC17EA809
|
_sceRtcGetLastReincarnatedTick
Version |
NID
|
1.69-3.60 |
0xE13D0FE5
|
_sceRtcGetLastAdjustedTick
Version |
NID
|
1.69-3.60 |
0xEA157EC5
|
_sceRtcGetCurrentAdNetworkTick
Version |
NID
|
3.60 |
0x76EFA8FE
|
_sceRtcGetCurrentDebugNetworkTick
Version |
NID
|
3.60 |
0xBF639B21
|
How to get current time and date
See also Rtc Tick.
Getting the current time and date involves Syscon scratchpad and Syscon command 0x11. Syscon command 0x11 returns twice the number of seconds Syscon has been running since its power on. Syscon scratchpad contains at offset 0x10 the timestamp when Syscon "started" running. It is stored in the following format: microseconds since 01/01/0001 and divided by 2^19. By adding those values together, the OS obtains the current time and date.
In pseudocode:
last_reincarnated_tick = syscon_read_scratchpad(offset=0x10, size=5)
up_time_half_seconds = syscon_cmd_read(cmd=0x11, size=4)
UTC = timedelta(microseconds=last_reincarnated_tick * (1<<19)) + datetime(1, 1, 1) + timedelta(seconds=up_time_half_seconds*2)
See also