mirror of
https://github.com/RPCS3/rpcs3
synced 2024-11-02 11:45:30 +00:00
cellRtc: improvements
This commit is contained in:
parent
56692e23f5
commit
c8e624850b
2 changed files with 168 additions and 246 deletions
|
@ -9,7 +9,6 @@
|
|||
|
||||
LOG_CHANNEL(cellRtc);
|
||||
|
||||
// clang-format off
|
||||
template <>
|
||||
void fmt_class_string<CellRtcError>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
@ -36,54 +35,6 @@ void fmt_class_string<CellRtcError>::format(std::string& out, u64 arg)
|
|||
return unknown;
|
||||
});
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
// Grabbed from JPCSP
|
||||
// This is the # of microseconds between January 1, 0001 and January 1, 1970.
|
||||
constexpr u64 RTC_MAGIC_OFFSET = 62135596800000000ULL;
|
||||
// This is the # of microseconds between January 1, 0001 and January 1, 1601 (for Win32 FILETIME.)
|
||||
constexpr u64 RTC_FILETIME_OFFSET = 50491123200000000ULL;
|
||||
|
||||
constexpr u64 EPOCH_AS_FILETIME = 116444736000000000ULL;
|
||||
|
||||
// Also stores leap year
|
||||
constexpr u8 DAYS_IN_MONTH[24] = {0x1F, 0x1C, 0x1F, 0x1E, 0x1F, 0x1E, 0x1F, 0x1F, 0x1E, 0x1F, 0x1E, 0x1F, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1E, 0x1F, 0x1F, 0x1E, 0x1F, 0x1E, 0x1F};
|
||||
|
||||
s64 convertToUNIXTime(u16 seconds, u16 minutes, u16 hours, u16 days, s32 years)
|
||||
{
|
||||
return s64{seconds} + s64{minutes} * 60 + s64{hours} * 3600 + s64{days} * 86400 + s64{s64{years} - 70} * 31536000 + s64{(years - 69) / 4} * 86400 - s64{(years - 1) / 100} * 86400 +
|
||||
s64{(years + 299) / 400} * 86400;
|
||||
}
|
||||
|
||||
u64 convertToWin32FILETIME(u16 seconds, u16 minutes, u16 hours, u16 days, s32 years)
|
||||
{
|
||||
s64 unixtime = convertToUNIXTime(seconds, minutes, hours, days, years);
|
||||
u64 win32time = static_cast<u64>(unixtime) * 10000000 + EPOCH_AS_FILETIME;
|
||||
u64 win32filetime = win32time | win32time >> 32;
|
||||
return win32filetime;
|
||||
}
|
||||
|
||||
// TODO make all this use tick resolution and figure out the magic numbers
|
||||
// TODO MULHDU instruction returns high 64 bit of the 128 bit result of two 64-bit regs multiplication
|
||||
// need to be replaced with utils::mulh64, utils::umulh64, utils::div128, utils::udiv128 in needed places
|
||||
// cellRtcSetTick / cellRtcSetWin32FileTime / cellRtcSetCurrentTick / cellRtcSetCurrentSecureTick
|
||||
// TODO undo optimized division
|
||||
|
||||
// Internal helper functions in cellRtc
|
||||
|
||||
error_code set_secure_rtc_time(u64 time)
|
||||
{
|
||||
return sys_ss_secure_rtc(0x3003 /* SET_TIME */, time, 0, 0); // TODO
|
||||
}
|
||||
|
||||
error_code get_secure_rtc_time(u64 unk1, u64 unk2, u64 unk3)
|
||||
{
|
||||
return sys_ss_secure_rtc(0x3002 /* GET_TIME */, unk1, unk2, unk3); // TODO
|
||||
}
|
||||
|
||||
// End of internal helper functions
|
||||
|
||||
// Helper methods
|
||||
|
||||
static inline char ascii(u8 num)
|
||||
{
|
||||
|
@ -100,11 +51,9 @@ static bool is_leap_year(u32 year)
|
|||
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
|
||||
}
|
||||
|
||||
// End of helper methods
|
||||
|
||||
error_code cellRtcGetCurrentTick(vm::ptr<CellRtcTick> pTick)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetCurrentTick(pTick=*0x%x)", pTick);
|
||||
cellRtc.trace("cellRtcGetCurrentTick(pTick=*0x%x)", pTick);
|
||||
|
||||
if (!vm::check_addr(pTick.addr()))
|
||||
{
|
||||
|
@ -115,7 +64,7 @@ error_code cellRtcGetCurrentTick(vm::ptr<CellRtcTick> pTick)
|
|||
vm::var<s64> nsec;
|
||||
|
||||
error_code ret = sys_time_get_current_time(sec, nsec);
|
||||
if (ret != CELL_OK)
|
||||
if (ret < CELL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
@ -127,7 +76,7 @@ error_code cellRtcGetCurrentTick(vm::ptr<CellRtcTick> pTick)
|
|||
|
||||
error_code cellRtcGetCurrentClock(vm::ptr<CellRtcDateTime> pClock, s32 iTimeZone)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetCurrentClock(pClock=*0x%x, iTimeZone=%d)", pClock, iTimeZone);
|
||||
cellRtc.notice("cellRtcGetCurrentClock(pClock=*0x%x, iTimeZone=%d)", pClock, iTimeZone);
|
||||
|
||||
if (!vm::check_addr(pClock.addr()))
|
||||
{
|
||||
|
@ -144,7 +93,7 @@ error_code cellRtcGetCurrentClock(vm::ptr<CellRtcDateTime> pClock, s32 iTimeZone
|
|||
vm::var<s64> nsec;
|
||||
|
||||
error_code ret = sys_time_get_current_time(sec, nsec);
|
||||
if (ret != CELL_OK)
|
||||
if (ret < CELL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
@ -159,7 +108,7 @@ error_code cellRtcGetCurrentClock(vm::ptr<CellRtcDateTime> pClock, s32 iTimeZone
|
|||
|
||||
error_code cellRtcGetCurrentClockLocalTime(vm::ptr<CellRtcDateTime> pClock)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetCurrentClockLocalTime(pClock=*0x%x)", pClock);
|
||||
cellRtc.trace("cellRtcGetCurrentClockLocalTime(pClock=*0x%x)", pClock);
|
||||
|
||||
if (!vm::check_addr(pClock.addr()))
|
||||
{
|
||||
|
@ -170,7 +119,7 @@ error_code cellRtcGetCurrentClockLocalTime(vm::ptr<CellRtcDateTime> pClock)
|
|||
vm::var<s32> summertime;
|
||||
|
||||
error_code ret = sys_time_get_timezone(timezone, summertime);
|
||||
if (ret != CELL_OK)
|
||||
if (ret < CELL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
@ -190,14 +139,14 @@ error_code cellRtcGetCurrentClockLocalTime(vm::ptr<CellRtcDateTime> pClock)
|
|||
vm::var<s64> nsec;
|
||||
|
||||
ret = sys_time_get_current_time(sec, nsec);
|
||||
if (ret != CELL_OK)
|
||||
if (ret < CELL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
tick->tick = *nsec / 1000 + *sec * cellRtcGetTickResolution() + RTC_MAGIC_OFFSET;
|
||||
|
||||
cellRtcTickAddMinutes(tick, tick, s64{*timezone} + s64{*summertime});
|
||||
cellRtcTickAddMinutes(tick, tick, *timezone + *summertime);
|
||||
cellRtcSetTick(pClock, tick);
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -319,7 +268,7 @@ error_code cellRtcFormatRfc2822LocalTime(vm::ptr<char> pszDateTime, vm::cptr<Cel
|
|||
vm::var<s32> summertime;
|
||||
|
||||
error_code ret = sys_time_get_timezone(timezone, summertime);
|
||||
if (ret != CELL_OK)
|
||||
if (ret < CELL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
@ -449,7 +398,7 @@ error_code cellRtcFormatRfc3339LocalTime(vm::ptr<char> pszDateTime, vm::cptr<Cel
|
|||
vm::var<s32> summertime;
|
||||
|
||||
error_code ret = sys_time_get_timezone(timezone, summertime);
|
||||
if (ret != CELL_OK)
|
||||
if (ret < CELL_OK)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
@ -773,7 +722,7 @@ error_code cellRtcParseDateTime(vm::ptr<CellRtcTick> pUtc, vm::cptr<char> pszDat
|
|||
cellRtc.warning("cellRtcParseDateTime(): ASCII value 0x%x at position %d is not a digit", pszDateTime[pos], pos);
|
||||
}
|
||||
|
||||
day = digit(pszDateTime[pos]);
|
||||
day = static_cast<u16>(pszDateTime[pos]) - '0'; // Needs to be sign extended first to match LLE for values from 0x80 to 0xb0
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
@ -1006,7 +955,7 @@ error_code cellRtcParseRfc3339(vm::ptr<CellRtcTick> pUtc, vm::cptr<char> pszDate
|
|||
|
||||
error_code cellRtcGetTick(vm::cptr<CellRtcDateTime> pTime, vm::ptr<CellRtcTick> pTick)
|
||||
{
|
||||
cellRtc.notice("cellRtcGetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick);
|
||||
cellRtc.trace("cellRtcGetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick);
|
||||
|
||||
if (!vm::check_addr(pTime.addr()))
|
||||
{
|
||||
|
@ -1110,7 +1059,7 @@ u64 date_time_to_tick(CellRtcDateTime date_time)
|
|||
|
||||
error_code cellRtcSetTick(vm::ptr<CellRtcDateTime> pTime, vm::cptr<CellRtcTick> pTick)
|
||||
{
|
||||
cellRtc.notice("cellRtcSetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick);
|
||||
cellRtc.trace("cellRtcSetTick(pTime=*0x%x, pTick=*0x%x)", pTime, pTick);
|
||||
|
||||
if (!vm::check_addr(pTime.addr()))
|
||||
{
|
||||
|
@ -1262,7 +1211,7 @@ error_code cellRtcTickAddWeeks(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick
|
|||
|
||||
error_code cellRtcTickAddMonths(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s32 iAdd)
|
||||
{
|
||||
cellRtc.trace("cellRtcTickAddMonths(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd);
|
||||
cellRtc.notice("cellRtcTickAddMonths(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd);
|
||||
|
||||
if (!vm::check_addr(pTick0.addr()))
|
||||
{
|
||||
|
@ -1277,41 +1226,28 @@ error_code cellRtcTickAddMonths(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTic
|
|||
vm::var<CellRtcDateTime> date_time;
|
||||
cellRtcSetTick(date_time, pTick1);
|
||||
|
||||
// Not pretty, but works
|
||||
const s32 total_months = date_time->year * 12 + date_time->month + iAdd - 1;
|
||||
const u16 new_year = total_months / 12;
|
||||
const u16 new_month = total_months - new_year * 12 + 1;
|
||||
|
||||
s64 total_months = (date_time->year * 12ULL) + date_time->month + iAdd + -1;
|
||||
s32 total_months_s32 = ::narrow<s32>(total_months);
|
||||
u32 unk_1 = total_months_s32 >> 0x1f;
|
||||
u64 unk_2 = ((total_months_s32 / 6 + unk_1) >> 1) - unk_1;
|
||||
u32 unk_3 = ::narrow<u32>(unk_2);
|
||||
unk_1 = unk_3 & 0xffff;
|
||||
u64 unk_4 = (total_months - ((u64{unk_3} << 4) - (unk_3 << 2))) + 1;
|
||||
if (((unk_2 & 0xffff) == 0) || ((unk_3 = unk_4 & 0xffff, (unk_4 & 0xffff) == 0 || unk_3 > 12)))
|
||||
u16 month_days;
|
||||
|
||||
if (new_year == 0u || new_month < 1u || new_month > 12u)
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
u32 uVar1 = ((s64{unk_1} * 0x51eb851f) >> 0x20);
|
||||
|
||||
// Leap year check
|
||||
u32 month_idx;
|
||||
if ((unk_1 == (uVar1 >> 7) * 400) || ((unk_1 != (uVar1 >> 5) * 100 && ((unk_2 & 3) == 0))))
|
||||
{
|
||||
month_idx = unk_3 + 11;
|
||||
month_days = static_cast<u16>(CELL_RTC_ERROR_INVALID_ARG); // LLE writes the error to this variable
|
||||
}
|
||||
else
|
||||
{
|
||||
month_idx = unk_3 - 1;
|
||||
month_days = is_leap_year(new_year) ? DAYS_IN_MONTH_LEAP[new_month - 1] : DAYS_IN_MONTH[new_month - 1];
|
||||
}
|
||||
u32 month_days = DAYS_IN_MONTH[month_idx];
|
||||
|
||||
if (month_days < date_time->day)
|
||||
{
|
||||
date_time->day = month_days;
|
||||
}
|
||||
|
||||
date_time->month = ::narrow<u16>(unk_4);
|
||||
date_time->year = ::narrow<u16>(unk_2);
|
||||
date_time->month = new_month;
|
||||
date_time->year = new_year;
|
||||
cellRtcGetTick(date_time, pTick0);
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -1319,7 +1255,7 @@ error_code cellRtcTickAddMonths(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTic
|
|||
|
||||
error_code cellRtcTickAddYears(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s32 iAdd)
|
||||
{
|
||||
cellRtc.trace("cellRtcTickAddYears(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd);
|
||||
cellRtc.notice("cellRtcTickAddYears(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d)", pTick0, pTick1, iAdd);
|
||||
|
||||
if (!vm::check_addr(pTick0.addr()))
|
||||
{
|
||||
|
@ -1334,33 +1270,26 @@ error_code cellRtcTickAddYears(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick
|
|||
vm::var<CellRtcDateTime> date_time;
|
||||
cellRtcSetTick(date_time, pTick1);
|
||||
|
||||
u64 total_years = iAdd + date_time->year;
|
||||
u32 unk_1 = total_years & 0xffff;
|
||||
if (unk_1 == 0 || date_time->month == 0 || date_time->month > 12)
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_ARG;
|
||||
}
|
||||
const u16 month = date_time->month;
|
||||
const u16 new_year = date_time->year + iAdd;
|
||||
|
||||
u32 uVar1 = ((s64{unk_1} * 0x51eb851f) >> 0x20);
|
||||
u16 month_days;
|
||||
|
||||
// Leap year check
|
||||
u32 month_idx;
|
||||
if ((unk_1 == (uVar1 >> 7) * 400) || ((unk_1 != (uVar1 >> 5) * 100 && ((total_years & 3) == 0))))
|
||||
if (new_year == 0u || month < 1u || month > 12u)
|
||||
{
|
||||
month_idx = date_time->month + 0xb;
|
||||
month_days = static_cast<u16>(CELL_RTC_ERROR_INVALID_ARG); // LLE writes the error to this variable
|
||||
}
|
||||
else
|
||||
{
|
||||
month_idx = date_time->month - 1;
|
||||
month_days = is_leap_year(new_year) ? DAYS_IN_MONTH_LEAP[month - 1] : DAYS_IN_MONTH[month - 1];
|
||||
}
|
||||
u32 month_days = DAYS_IN_MONTH[month_idx];
|
||||
|
||||
if (month_days < date_time->day)
|
||||
{
|
||||
date_time->day = month_days;
|
||||
}
|
||||
|
||||
date_time->year = ::narrow<u16>(total_years);
|
||||
date_time->year = new_year;
|
||||
cellRtcGetTick(date_time, pTick0);
|
||||
|
||||
return CELL_OK;
|
||||
|
@ -1368,7 +1297,7 @@ error_code cellRtcTickAddYears(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick
|
|||
|
||||
error_code cellRtcConvertUtcToLocalTime(vm::cptr<CellRtcTick> pUtc, vm::ptr<CellRtcTick> pLocalTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcConvertUtcToLocalTime(pUtc=*0x%x, pLocalTime=*0x%x)", pUtc, pLocalTime);
|
||||
cellRtc.trace("cellRtcConvertUtcToLocalTime(pUtc=*0x%x, pLocalTime=*0x%x)", pUtc, pLocalTime);
|
||||
|
||||
vm::var<s32> timezone;
|
||||
vm::var<s32> summertime;
|
||||
|
@ -1376,7 +1305,7 @@ error_code cellRtcConvertUtcToLocalTime(vm::cptr<CellRtcTick> pUtc, vm::ptr<Cell
|
|||
error_code ret = sys_time_get_timezone(timezone, summertime);
|
||||
if (-1 < ret)
|
||||
{
|
||||
ret = cellRtcTickAddMinutes(pLocalTime, pUtc, s64{*timezone} + s64{*summertime});
|
||||
ret = cellRtcTickAddMinutes(pLocalTime, pUtc, *timezone + *summertime);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1384,7 +1313,7 @@ error_code cellRtcConvertUtcToLocalTime(vm::cptr<CellRtcTick> pUtc, vm::ptr<Cell
|
|||
|
||||
error_code cellRtcConvertLocalTimeToUtc(vm::cptr<CellRtcTick> pLocalTime, vm::ptr<CellRtcTick> pUtc)
|
||||
{
|
||||
cellRtc.todo("cellRtcConvertLocalTimeToUtc(pLocalTime=*0x%x, pUtc=*0x%x)", pLocalTime, pUtc);
|
||||
cellRtc.notice("cellRtcConvertLocalTimeToUtc(pLocalTime=*0x%x, pUtc=*0x%x)", pLocalTime, pUtc);
|
||||
|
||||
vm::var<s32> timezone;
|
||||
vm::var<s32> summertime;
|
||||
|
@ -1392,7 +1321,7 @@ error_code cellRtcConvertLocalTimeToUtc(vm::cptr<CellRtcTick> pLocalTime, vm::pt
|
|||
error_code ret = sys_time_get_timezone(timezone, summertime);
|
||||
if (-1 < ret)
|
||||
{
|
||||
ret = cellRtcTickAddMinutes(pUtc, pLocalTime, -(s64{*timezone} + s64{*summertime}));
|
||||
ret = cellRtcTickAddMinutes(pUtc, pLocalTime, -(*timezone + *summertime));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1400,23 +1329,41 @@ error_code cellRtcConvertLocalTimeToUtc(vm::cptr<CellRtcTick> pLocalTime, vm::pt
|
|||
|
||||
error_code cellRtcGetCurrentSecureTick(vm::ptr<CellRtcTick> tick)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetCurrentSecureTick(*0x%x)", tick);
|
||||
cellRtc.notice("cellRtcGetCurrentSecureTick(tick=*0x%x)", tick);
|
||||
|
||||
if (!vm::check_addr(tick.addr()))
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
// TODO
|
||||
tick->tick = RTC_SYSTEM_TIME_MIN;
|
||||
|
||||
tick->tick = 0xe01d003a63a000;
|
||||
const vm::var<u64> time{0};
|
||||
const vm::var<u64> status{0};
|
||||
|
||||
return CELL_OK;
|
||||
error_code ret = sys_ss_secure_rtc(0x3002, 0, time.addr(), status.addr());
|
||||
|
||||
if (ret >= CELL_OK)
|
||||
{
|
||||
tick->tick += *time * cellRtcGetTickResolution();
|
||||
}
|
||||
else if (ret == static_cast<s32>(SYS_SS_RTC_ERROR_UNK))
|
||||
{
|
||||
switch (*status)
|
||||
{
|
||||
case 1: ret = CELL_RTC_ERROR_NO_CLOCK; break;
|
||||
case 2: ret = CELL_RTC_ERROR_NOT_INITIALIZED; break;
|
||||
case 4: ret = CELL_RTC_ERROR_INVALID_VALUE; break;
|
||||
case 8: ret = CELL_RTC_ERROR_NO_CLOCK; break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
error_code cellRtcGetDosTime(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<u32> puiDosTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetDosTime(pDateTime=*0x%x, puiDosTime=*0x%x)", pDateTime, puiDosTime);
|
||||
cellRtc.notice("cellRtcGetDosTime(pDateTime=*0x%x, puiDosTime=*0x%x)", pDateTime, puiDosTime);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
|
@ -1430,27 +1377,26 @@ error_code cellRtcGetDosTime(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<u32> p
|
|||
|
||||
if (pDateTime->year < 1980)
|
||||
{
|
||||
if (puiDosTime)
|
||||
if (puiDosTime) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*puiDosTime = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (pDateTime->year >= 2108)
|
||||
{
|
||||
if (puiDosTime)
|
||||
{
|
||||
*puiDosTime = 0xff9fbf7d; // kHighDosTime
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!puiDosTime)
|
||||
{
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pDateTime->year >= 2108)
|
||||
{
|
||||
if (puiDosTime) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*puiDosTime = 0xff9fbf7d; // kHighDosTime
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (puiDosTime) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
s32 year = ((pDateTime->year - 1980) & 0x7F) << 9;
|
||||
s32 month = ((pDateTime->month) & 0xF) << 5;
|
||||
s32 hour = ((pDateTime->hour) & 0x1F) << 11;
|
||||
|
@ -1460,65 +1406,59 @@ error_code cellRtcGetDosTime(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<u32> p
|
|||
s32 ymd = year | month | day;
|
||||
s32 hms = hour | minute | second;
|
||||
*puiDosTime = (ymd << 16) | hms;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
return -1;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellRtcGetSystemTime(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<CellRtcTick> pTick)
|
||||
error_code cellRtcGetSystemTime(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<s64> pTimeStamp)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetSystemTime(pDateTime=*0x%x, pTick=*0x%x)", pDateTime, pTick);
|
||||
cellRtc.notice("cellRtcGetSystemTime(pDateTime=*0x%x, pTimeStamp=*0x%x)", pDateTime, pTimeStamp);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
if (!vm::check_addr(pTick.addr()))
|
||||
if (!vm::check_addr(pTimeStamp.addr()))
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
error_code ret;
|
||||
vm::var<CellRtcTick> tick;
|
||||
cellRtcGetTick(pDateTime, tick);
|
||||
|
||||
if (tick->tick < 63082281600000000) // Max time
|
||||
if (tick->tick < RTC_SYSTEM_TIME_MIN)
|
||||
{
|
||||
ret = CELL_RTC_ERROR_INVALID_VALUE;
|
||||
if (pTick)
|
||||
if (pTimeStamp) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
pTick->tick = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tick->tick < 0xeb5325dc3ec23f) // 66238041600999999
|
||||
{
|
||||
ret = CELL_OK;
|
||||
if (pTick)
|
||||
{
|
||||
pTick->tick = (tick->tick + 0xff1fe2ffc59c6000) / cellRtcGetTickResolution();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = CELL_RTC_ERROR_INVALID_VALUE;
|
||||
if (pTick)
|
||||
{
|
||||
pTick->tick = 0xbc19137f; // 1 day?
|
||||
}
|
||||
*pTimeStamp = 0;
|
||||
}
|
||||
|
||||
return CELL_RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (tick->tick >= RTC_SYSTEM_TIME_MAX + cellRtcGetTickResolution())
|
||||
{
|
||||
if (pTimeStamp) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*pTimeStamp = (RTC_SYSTEM_TIME_MAX - RTC_SYSTEM_TIME_MIN) / cellRtcGetTickResolution();
|
||||
}
|
||||
|
||||
return CELL_RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (pTimeStamp) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*pTimeStamp = (tick->tick - RTC_SYSTEM_TIME_MIN) / cellRtcGetTickResolution();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellRtcGetTime_t(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<s64> piTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetTime_t(pDateTime=*0x%x, piTime=*0x%x)", pDateTime, piTime);
|
||||
cellRtc.notice("cellRtcGetTime_t(pDateTime=*0x%x, piTime=*0x%x)", pDateTime, piTime);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
|
@ -1533,30 +1473,27 @@ error_code cellRtcGetTime_t(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<s64> pi
|
|||
vm::var<CellRtcTick> tick;
|
||||
cellRtcGetTick(pDateTime, tick);
|
||||
|
||||
error_code ret;
|
||||
if (tick->tick < RTC_MAGIC_OFFSET)
|
||||
{
|
||||
ret = CELL_RTC_ERROR_INVALID_VALUE;
|
||||
if (piTime)
|
||||
if (piTime) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*piTime = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = CELL_OK;
|
||||
if (piTime)
|
||||
{
|
||||
*piTime = (tick->tick + 0xff23400100d44000) / cellRtcGetTickResolution();
|
||||
}
|
||||
|
||||
return CELL_RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (piTime) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*piTime = (tick->tick - RTC_MAGIC_OFFSET) / cellRtcGetTickResolution();
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellRtcGetWin32FileTime(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<u64> pulWin32FileTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetWin32FileTime(pDateTime=*0x%x, pulWin32FileTime=*0x%x)", pDateTime, pulWin32FileTime);
|
||||
cellRtc.notice("cellRtcGetWin32FileTime(pDateTime=*0x%x, pulWin32FileTime=*0x%x)", pDateTime, pulWin32FileTime);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
|
@ -1571,83 +1508,73 @@ error_code cellRtcGetWin32FileTime(vm::cptr<CellRtcDateTime> pDateTime, vm::ptr<
|
|||
vm::var<CellRtcTick> tick;
|
||||
cellRtcGetTick(pDateTime, tick);
|
||||
|
||||
error_code ret;
|
||||
if (tick->tick < RTC_FILETIME_OFFSET)
|
||||
{
|
||||
ret = CELL_RTC_ERROR_INVALID_VALUE;
|
||||
if (pulWin32FileTime)
|
||||
if (pulWin32FileTime) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*pulWin32FileTime = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = CELL_OK;
|
||||
if (pulWin32FileTime)
|
||||
{
|
||||
*pulWin32FileTime = tick->tick * 10 + 0xf8fe31e8dd890000;
|
||||
}
|
||||
|
||||
return CELL_RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (pulWin32FileTime) // Should always evaluate to true, nullptr was already checked above
|
||||
{
|
||||
*pulWin32FileTime = (tick->tick - RTC_FILETIME_OFFSET) * 10;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellRtcSetCurrentSecureTick(vm::ptr<CellRtcTick> pTick)
|
||||
{
|
||||
cellRtc.todo("cellRtcSetCurrentSecureTick(pTick=*0x%x)", pTick);
|
||||
cellRtc.notice("cellRtcSetCurrentSecureTick(pTick=*0x%x)", pTick);
|
||||
|
||||
if (!pTick)
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
u64 uVar1 = pTick->tick + 0xff1fe2ffc59c6000;
|
||||
if (uVar1 >= 0xb3625a1cbe000) // 3155760000000000
|
||||
if (pTick->tick > RTC_SYSTEM_TIME_MAX)
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
return set_secure_rtc_time(uVar1 / cellRtcGetTickResolution());
|
||||
return sys_ss_secure_rtc(0x3003, (pTick->tick - RTC_SYSTEM_TIME_MIN) / cellRtcGetTickResolution(), 0, 0);
|
||||
}
|
||||
|
||||
error_code cellRtcSetCurrentTick(vm::cptr<CellRtcTick> pTick)
|
||||
{
|
||||
cellRtc.todo("cellRtcSetCurrentTick(pTick=*0x%x)", pTick);
|
||||
cellRtc.notice("cellRtcSetCurrentTick(pTick=*0x%x)", pTick);
|
||||
|
||||
if (!pTick)
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_POINTER;
|
||||
}
|
||||
|
||||
//u64 tmp = pTick->tick + 0xff23400100d44000;
|
||||
if (!(0xdcbffeff2bbfff < pTick->tick))
|
||||
if (pTick->tick < RTC_MAGIC_OFFSET)
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_ARG;
|
||||
return CELL_RTC_ERROR_INVALID_VALUE;
|
||||
}
|
||||
|
||||
// TODO syscall not implemented
|
||||
/*
|
||||
u64 tmp2 = sys_time_get_system_time(tmp / cellRtcGetTickResolution(), (tmp % cellRtcGetTickResolution()) * 1000);
|
||||
const u64 unix_time = pTick->tick - RTC_MAGIC_OFFSET;
|
||||
|
||||
return (tmp2 & (tmp2 | tmp2 - 1) >> 0x1f);
|
||||
*/
|
||||
return CELL_OK;
|
||||
const error_code ret = sys_time_set_current_time(unix_time / cellRtcGetTickResolution(), unix_time % cellRtcGetTickResolution() * 1000);
|
||||
|
||||
return ret >= CELL_OK ? CELL_OK : ret;
|
||||
}
|
||||
|
||||
error_code cellRtcSetConf(s64 unk1, s64 unk2, u32 timezone, u32 summertime)
|
||||
{
|
||||
cellRtc.todo("cellRtcSetConf(unk1=0x%x, unk2=0x%x, timezone=%d, summertime=%d)", unk1, unk2, timezone, summertime);
|
||||
cellRtc.notice("cellRtcSetConf(unk1=0x%x, unk2=0x%x, timezone=%d, summertime=%d)", unk1, unk2, timezone, summertime);
|
||||
// Seems the first 2 args are ignored :|
|
||||
|
||||
// TODO Syscall not implemented
|
||||
// return sys_time_set_timezone(timezone, summertime);
|
||||
|
||||
return CELL_OK;
|
||||
return sys_time_set_timezone(timezone, summertime);
|
||||
}
|
||||
|
||||
error_code cellRtcSetDosTime(vm::ptr<CellRtcDateTime> pDateTime, u32 uiDosTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcSetDosTime(pDateTime=*0x%x, uiDosTime=0x%x)", pDateTime, uiDosTime);
|
||||
cellRtc.notice("cellRtcSetDosTime(pDateTime=*0x%x, uiDosTime=0x%x)", pDateTime, uiDosTime);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
|
@ -1668,7 +1595,7 @@ error_code cellRtcSetDosTime(vm::ptr<CellRtcDateTime> pDateTime, u32 uiDosTime)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 cellRtcGetTickResolution()
|
||||
constexpr u32 cellRtcGetTickResolution()
|
||||
{
|
||||
// Amount of ticks in a second
|
||||
return 1000000;
|
||||
|
@ -1676,7 +1603,7 @@ u32 cellRtcGetTickResolution()
|
|||
|
||||
error_code cellRtcSetTime_t(vm::ptr<CellRtcDateTime> pDateTime, u64 iTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcSetTime_t(pDateTime=*0x%x, iTime=0x%llx)", pDateTime, iTime);
|
||||
cellRtc.notice("cellRtcSetTime_t(pDateTime=*0x%x, iTime=0x%llx)", pDateTime, iTime);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
|
@ -1693,7 +1620,7 @@ error_code cellRtcSetTime_t(vm::ptr<CellRtcDateTime> pDateTime, u64 iTime)
|
|||
|
||||
error_code cellRtcSetSystemTime(vm::ptr<CellRtcDateTime> pDateTime, u64 iTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcSetSystemTime(pDateTime=*0x%x, iTime=0x%llx)", pDateTime, iTime);
|
||||
cellRtc.notice("cellRtcSetSystemTime(pDateTime=*0x%x, iTime=0x%llx)", pDateTime, iTime);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
|
@ -1701,14 +1628,16 @@ error_code cellRtcSetSystemTime(vm::ptr<CellRtcDateTime> pDateTime, u64 iTime)
|
|||
}
|
||||
|
||||
vm::var<CellRtcTick> tick;
|
||||
tick->tick = iTime * cellRtcGetTickResolution() + 0xe01d003a63a000;
|
||||
tick->tick = iTime * cellRtcGetTickResolution() + RTC_SYSTEM_TIME_MIN;
|
||||
|
||||
return cellRtcSetTick(pDateTime, tick);
|
||||
cellRtcSetTick(pDateTime, tick);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellRtcSetWin32FileTime(vm::ptr<CellRtcDateTime> pDateTime, u64 ulWin32FileTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcSetWin32FileTime(pDateTime=*0x%x, ulWin32FileTime=0x%llx)", pDateTime, ulWin32FileTime);
|
||||
cellRtc.notice("cellRtcSetWin32FileTime(pDateTime=*0x%x, ulWin32FileTime=0x%llx)", pDateTime, ulWin32FileTime);
|
||||
|
||||
if (!vm::check_addr(pDateTime.addr()))
|
||||
{
|
||||
|
@ -1723,7 +1652,7 @@ error_code cellRtcSetWin32FileTime(vm::ptr<CellRtcDateTime> pDateTime, u64 ulWin
|
|||
|
||||
error_code cellRtcIsLeapYear(s32 year)
|
||||
{
|
||||
cellRtc.todo("cellRtcIsLeapYear(year=%d)", year);
|
||||
cellRtc.notice("cellRtcIsLeapYear(year=%d)", year);
|
||||
|
||||
if (year < 1)
|
||||
{
|
||||
|
@ -1735,22 +1664,17 @@ error_code cellRtcIsLeapYear(s32 year)
|
|||
|
||||
error_code cellRtcGetDaysInMonth(s32 year, s32 month)
|
||||
{
|
||||
cellRtc.todo("cellRtcGetDaysInMonth(year=%d, month=%d)", year, month);
|
||||
cellRtc.notice("cellRtcGetDaysInMonth(year=%d, month=%d)", year, month);
|
||||
|
||||
if ((year <= 0) || (month <= 0) || (month > 12))
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (is_leap_year(year))
|
||||
{
|
||||
return not_an_error(DAYS_IN_MONTH[month + 11]);
|
||||
}
|
||||
|
||||
return not_an_error(DAYS_IN_MONTH[month - 1]);
|
||||
return not_an_error(is_leap_year(year) ? DAYS_IN_MONTH_LEAP[month - 1] : DAYS_IN_MONTH[month - 1]);
|
||||
}
|
||||
|
||||
error_code cellRtcGetDayOfWeek(s32 year, s32 month, s32 day)
|
||||
s32 cellRtcGetDayOfWeek(s32 year, s32 month, s32 day)
|
||||
{
|
||||
cellRtc.trace("cellRtcGetDayOfWeek(year=%d, month=%d, day=%d)", year, month, day);
|
||||
|
||||
|
@ -1760,13 +1684,16 @@ error_code cellRtcGetDayOfWeek(s32 year, s32 month, s32 day)
|
|||
month += 12;
|
||||
}
|
||||
|
||||
return not_an_error(((month * 0xd + 8) / 5 + ((year + (year >> 2) + (year < 0 && (year & 3U) != 0)) - year / 100) + year / 400 + day) % 7);
|
||||
return ((month * 13 + 8) / 5 + year + year / 4 - year / 100 + year / 400 + day) % 7;
|
||||
}
|
||||
|
||||
error_code cellRtcCheckValid(vm::cptr<CellRtcDateTime> pTime)
|
||||
{
|
||||
cellRtc.todo("cellRtcCheckValid(pTime=*0x%x)", pTime);
|
||||
cellRtc.todo("cellRtcCheckValid year: %d, month: %d, day: %d, hour: %d, minute: %d, second: %d, microsecond: %d\n", pTime->year, pTime->month, pTime->day, pTime->hour, pTime->minute, pTime->second, pTime->microsecond);
|
||||
cellRtc.notice("cellRtcCheckValid(pTime=*0x%x)", pTime);
|
||||
|
||||
ensure(!!pTime); // Not checked on LLE
|
||||
|
||||
cellRtc.notice("cellRtcCheckValid year: %d, month: %d, day: %d, hour: %d, minute: %d, second: %d, microsecond: %d", pTime->year, pTime->month, pTime->day, pTime->hour, pTime->minute, pTime->second, pTime->microsecond);
|
||||
|
||||
if (pTime->year == 0 || pTime->year >= 10000)
|
||||
{
|
||||
|
@ -1778,19 +1705,9 @@ error_code cellRtcCheckValid(vm::cptr<CellRtcDateTime> pTime)
|
|||
return CELL_RTC_ERROR_INVALID_MONTH;
|
||||
}
|
||||
|
||||
s32 month_idx;
|
||||
const auto& days_in_month = is_leap_year(pTime->year) ? DAYS_IN_MONTH_LEAP : DAYS_IN_MONTH;
|
||||
|
||||
if (is_leap_year(pTime->year))
|
||||
{
|
||||
// Leap year check
|
||||
month_idx = pTime->month + 11;
|
||||
}
|
||||
else
|
||||
{
|
||||
month_idx = pTime->month - 1;
|
||||
}
|
||||
|
||||
if (pTime->day == 0 || pTime->day > DAYS_IN_MONTH[month_idx])
|
||||
if (pTime->day == 0 || pTime->day > days_in_month[pTime->month - 1])
|
||||
{
|
||||
return CELL_RTC_ERROR_INVALID_DAY;
|
||||
}
|
||||
|
@ -1818,9 +1735,11 @@ error_code cellRtcCheckValid(vm::cptr<CellRtcDateTime> pTime)
|
|||
return CELL_OK;
|
||||
}
|
||||
|
||||
error_code cellRtcCompareTick(vm::cptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1)
|
||||
s32 cellRtcCompareTick(vm::cptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1)
|
||||
{
|
||||
cellRtc.todo("cellRtcCompareTick(pTick0=*0x%x, pTick1=*0x%x)", pTick0, pTick1);
|
||||
cellRtc.notice("cellRtcCompareTick(pTick0=*0x%x, pTick1=*0x%x)", pTick0, pTick1);
|
||||
|
||||
ensure(!!pTick0 && !!pTick1); // Not checked on LLE
|
||||
|
||||
s32 ret = -1;
|
||||
if (pTick1->tick <= pTick0->tick)
|
||||
|
@ -1828,7 +1747,7 @@ error_code cellRtcCompareTick(vm::cptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick
|
|||
ret = pTick1->tick < pTick0->tick;
|
||||
}
|
||||
|
||||
return not_an_error(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
DECLARE(ppu_module_manager::cellRtc)
|
||||
|
|
|
@ -38,10 +38,18 @@ struct CellRtcDateTime
|
|||
be_t<u32> microsecond; // 0 to 999999
|
||||
};
|
||||
|
||||
constexpr u64 RTC_MAGIC_OFFSET = 62135596800000000ull; // 1970-01-01 00:00:00.000000
|
||||
constexpr u64 RTC_FILETIME_OFFSET = 50491123200000000ull; // 1601-01-01 00:00:00.000000
|
||||
constexpr u64 RTC_SYSTEM_TIME_MIN = 63082281600000000ull; // 2000-01-01 00:00:00.000000
|
||||
constexpr u64 RTC_SYSTEM_TIME_MAX = 66238041599999999ull; // 2099-12-31 23:59:59.999999
|
||||
|
||||
constexpr u32 DAYS_IN_400_YEARS = 365 * 400 + 97;
|
||||
constexpr u16 DAYS_IN_100_YEARS = 365 * 100 + 24;
|
||||
constexpr u16 DAYS_IN_4_YEARS = 365 * 4 + 1;
|
||||
|
||||
constexpr std::array<u8, 12> DAYS_IN_MONTH = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
constexpr std::array<u8, 12> DAYS_IN_MONTH_LEAP = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
|
||||
|
||||
constexpr std::array<u16, 13> MONTH_OFFSET = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, umax };
|
||||
constexpr std::array<u16, 13> MONTH_OFFSET_LEAP = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, umax };
|
||||
|
||||
|
@ -50,17 +58,12 @@ constexpr std::array<std::string_view, 12> MONTH_NAMES = { "january", "febru
|
|||
constexpr std::array<std::string_view, 70> TIME_ZONE_NAMES = { "gmt", "est", "edt", "cst", "cdt", "mst", "mdt", "pst", "pdt", "nzdt", "nzst", "idle", "nzt", "aesst", "acsst", "cadt", "sadt", "aest", "east", "gst", "ligt", "acst", "sast", "cast", "awsst", "jst", "kst", "wdt", "mt", "awst", "cct", "wadt", "wst", "jt", "wast", "it", "bt", "eetdst", "eet", "cetdst", "fwt", "ist", "mest", "metdst", "sst", "bst", "cet", "dnt", "fst", "met", "mewt", "mez", "nor", "set", "swt", "wetdst", "wet", "wat", "ndt", "adt", "nft", "nst", "ast", "ydt", "hdt", "yst", "ahst", "cat", "nt", "idlw" };
|
||||
constexpr std::array<s8, 70> TIME_ZONE_VALUES = { 0, -10, -8, -12, -10, -14, -12, -16, -14, 26, 24, 24, 24, 22, 21, 21, 21, 20, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 16, 16, 16, 16, 15, 14, 7, 6, 6, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, -2, -3, -6, -5, -5, -8, -16, -18, -18, -20, -20, -22, -24 }; // In units of 30 minutes
|
||||
|
||||
error_code cellRtcTickAddYears(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s32 iAdd);
|
||||
error_code cellRtcTickAddMonths(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s32 lAdd);
|
||||
error_code cellRtcTickAddDays(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s32 lAdd);
|
||||
error_code cellRtcTickAddHours(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s32 lAdd);
|
||||
error_code cellRtcTickAddMinutes(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s64 lAdd);
|
||||
error_code cellRtcTickAddSeconds(vm::ptr<CellRtcTick> pTick0, vm::cptr<CellRtcTick> pTick1, s64 lAdd);
|
||||
|
||||
error_code cellRtcSetTick(vm::ptr<CellRtcDateTime> pTime, vm::cptr<CellRtcTick> pTick);
|
||||
u32 cellRtcGetTickResolution();
|
||||
constexpr u32 cellRtcGetTickResolution();
|
||||
error_code cellRtcCheckValid(vm::cptr<CellRtcDateTime> pTime);
|
||||
error_code cellRtcGetDayOfWeek(s32 year, s32 month, s32 day);
|
||||
s32 cellRtcGetDayOfWeek(s32 year, s32 month, s32 day);
|
||||
error_code cellRtcGetTick(vm::cptr<CellRtcDateTime> pTime, vm::ptr<CellRtcTick> pTick);
|
||||
error_code cellRtcGetCurrentTick(vm::ptr<CellRtcTick> pTick);
|
||||
|
||||
|
|
Loading…
Reference in a new issue