From 649527a235609217c0216365220956e73a0a3a60 Mon Sep 17 00:00:00 2001 From: CrazyBloo Date: Fri, 6 Sep 2024 17:08:32 -0400 Subject: [PATCH] libSceRtc HLE (#697) * SetTick + GetTick, adding functions, checkvalid * format * more functions * format * implement lizardy's changes * fix linux build * various formatting improvements and fixes * fix sceRtcGetCurrentClockLocalTime, fixes sceRtcGetCurrentClockLocalTime using lizardy's suggestions. also implements various formatting improvements and logging changes * fix mac and linux builds, const for UNIX_EPOCH * fix ConvertUtcToLocalTime,RtcConvertLocalTimeToUtc * format rfc2822, format rfc3339 * format * GetDosTime, GetTime_t, GetWin32FileTime +various formatting improvements * sceRtcParseRFC3339, sceRtcParseDateTime --- src/core/libraries/kernel/libkernel.h | 2 + src/core/libraries/kernel/time_management.h | 7 +- src/core/libraries/rtc/rtc.cpp | 1130 ++++++++++++++++--- src/core/libraries/rtc/rtc.h | 112 +- src/core/libraries/rtc/rtc_error.h | 17 +- 5 files changed, 1095 insertions(+), 173 deletions(-) diff --git a/src/core/libraries/kernel/libkernel.h b/src/core/libraries/kernel/libkernel.h index c28a548f..73705cdc 100644 --- a/src/core/libraries/kernel/libkernel.h +++ b/src/core/libraries/kernel/libkernel.h @@ -33,6 +33,8 @@ typedef struct { } OrbisKernelUuid; int* PS4_SYSV_ABI __Error(); +int PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time, + struct OrbisTimesec* st, unsigned long* dst_sec); int PS4_SYSV_ABI sceKernelGetCompiledSdkVersion(int* ver); void LibKernel_Register(Core::Loader::SymbolsResolver* sym); diff --git a/src/core/libraries/kernel/time_management.h b/src/core/libraries/kernel/time_management.h index a28f8c13..a28e6e55 100644 --- a/src/core/libraries/kernel/time_management.h +++ b/src/core/libraries/kernel/time_management.h @@ -3,6 +3,8 @@ #pragma once +#include + #include "common/types.h" namespace Core::Loader { @@ -50,7 +52,10 @@ u64 PS4_SYSV_ABI sceKernelGetProcessTime(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounter(); u64 PS4_SYSV_ABI sceKernelGetProcessTimeCounterFrequency(); u64 PS4_SYSV_ABI sceKernelReadTsc(); - +int PS4_SYSV_ABI sceKernelClockGettime(s32 clock_id, OrbisKernelTimespec* tp); +s32 PS4_SYSV_ABI sceKernelGettimezone(OrbisKernelTimezone* tz); +int PS4_SYSV_ABI sceKernelConvertLocaltimeToUtc(time_t param_1, int64_t param_2, time_t* seconds, + OrbisKernelTimezone* timezone, int* dst_seconds); void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Kernel diff --git a/src/core/libraries/rtc/rtc.cpp b/src/core/libraries/rtc/rtc.cpp index 387a8558..7a46a1e3 100644 --- a/src/core/libraries/rtc/rtc.cpp +++ b/src/core/libraries/rtc/rtc.cpp @@ -5,156 +5,827 @@ #include "common/logging/log.h" #include "core/libraries/error_codes.h" +#include "core/libraries/kernel/libkernel.h" +#include "core/libraries/kernel/time_management.h" #include "core/libraries/libs.h" #include "rtc.h" #include "rtc_error.h" namespace Libraries::Rtc { -int PS4_SYSV_ABI sceRtcCheckValid() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcCheckValid(OrbisRtcDateTime* pTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + if (pTime->year == 0 || pTime->year > 9999) + return ORBIS_RTC_ERROR_INVALID_YEAR; + + if (pTime->month == 0 || pTime->month > 12) + return ORBIS_RTC_ERROR_INVALID_MONTH; + + if (pTime->day == 0) + return ORBIS_RTC_ERROR_INVALID_DAY; + + using namespace std::chrono; + year chronoYear = year(pTime->year); + month chronoMonth = month(pTime->month); + int lastDay = + static_cast(unsigned(year_month_day_last{chronoYear / chronoMonth / last}.day())); + + if (pTime->day > lastDay) + return ORBIS_RTC_ERROR_INVALID_DAY; + + if (pTime->hour >= 24) + return ORBIS_RTC_ERROR_INVALID_HOUR; + + if (pTime->minute >= 60) + return ORBIS_RTC_ERROR_INVALID_MINUTE; + + if (pTime->second >= 60) + return ORBIS_RTC_ERROR_INVALID_SECOND; + + if (pTime->microsecond >= 1000000) + return ORBIS_RTC_ERROR_INVALID_MICROSECOND; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcCompareTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcCompareTick(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + if (pTick1->tick <= pTick2->tick) + return 1; + else + return 0; + + return ORBIS_FAIL; } -int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc(OrbisRtcTick* pTickLocal, OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickLocal == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + time_t seconds; + Kernel::OrbisKernelTimezone timezone; + + int convertValue = Kernel::sceKernelConvertLocaltimeToUtc( + (pTickLocal->tick - UNIX_EPOCH_TICKS) / 1000000, 0xffffffff, &seconds, &timezone, 0); + + if (convertValue >= 0) { + convertValue = sceRtcTickAddMinutes( + pTickUtc, pTickLocal, -(((timezone.tz_dsttime * 60) - timezone.tz_minuteswest))); + } + + return convertValue; } -int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime(OrbisRtcTick* pTickUtc, OrbisRtcTick* pTickLocal) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickUtc == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimezone timeZone; + int returnValue = Kernel::sceKernelGettimezone(&timeZone); + + sceRtcTickAddMinutes(pTickLocal, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); + + return 0; } int PS4_SYSV_ABI sceRtcEnd() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; + return SCE_OK; } -int PS4_SYSV_ABI sceRtcFormatRFC2822() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC2822(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int iTimeZoneMinutes) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + OrbisRtcTick formatTick; + + if (pTickUtc == nullptr) { + sceRtcGetCurrentTick(&formatTick); + } else { + formatTick.tick = pTickUtc->tick; + } + + sceRtcTickAddMinutes(&formatTick, &formatTick, iTimeZoneMinutes); + + OrbisRtcDateTime formatTime; + sceRtcSetTick(&formatTime, &formatTick); + + int validTime = sceRtcCheckValid(&formatTime); + + std::string formattedString; + + if (validTime >= 0) { + int weekDay = sceRtcGetDayOfWeek(formatTime.year, formatTime.month, formatTime.day); + switch (weekDay) { + case 0: + formattedString = "Sun, "; + break; + case 1: + formattedString = "Mon, "; + break; + case 2: + formattedString = "Tue, "; + break; + case 3: + formattedString = "Wed, "; + break; + case 4: + formattedString = "Thu, "; + break; + case 5: + formattedString = "Fri, "; + break; + case 6: + formattedString = "Sat, "; + break; + } + + if (formatTime.day < 10) { + formattedString += "0" + std::to_string(formatTime.day) + " "; + } else { + formattedString += std::to_string(formatTime.day) + " "; + } + + switch (formatTime.month) { + case 1: + formattedString += "Jan "; + break; + case 2: + formattedString += "Feb "; + break; + case 3: + formattedString += "Mar "; + break; + case 4: + formattedString += "Apr "; + break; + case 5: + formattedString += "May "; + break; + case 6: + formattedString += "Jun "; + break; + case 7: + formattedString += "Jul "; + break; + case 8: + formattedString += "Aug "; + break; + case 9: + formattedString += "Sep "; + break; + case 10: + formattedString += "Oct "; + break; + case 11: + formattedString += "Nov "; + break; + case 12: + formattedString += "Dec "; + break; + } + + formattedString += std::to_string(formatTime.year) + " "; + + if (formatTime.hour < 10) { + formattedString += "0" + std::to_string(formatTime.hour) + ":"; + } else { + formattedString += std::to_string(formatTime.hour) + ":"; + } + + if (formatTime.minute < 10) { + formattedString += "0" + std::to_string(formatTime.minute) + ":"; + } else { + formattedString += std::to_string(formatTime.minute) + ":"; + } + + if (formatTime.second < 10) { + formattedString += "0" + std::to_string(formatTime.second) + " "; + } else { + formattedString += std::to_string(formatTime.second) + " "; + } + + if (iTimeZoneMinutes == 0) { + formattedString += "+0000"; + } else { + int timeZoneHours = iTimeZoneMinutes / 60; + int timeZoneRemainder = iTimeZoneMinutes % 60; + + if (timeZoneHours < 0) { + formattedString += "-"; + timeZoneHours *= -1; + } else { + formattedString += "+"; + } + + if (timeZoneHours < 10) { + formattedString += "0" + std::to_string(timeZoneHours); + } else { + formattedString += std::to_string(timeZoneHours); + } + + if (timeZoneRemainder == 0) { + formattedString += "00"; + } else { + if (timeZoneRemainder < 0) + timeZoneRemainder *= -1; + formattedString += std::to_string(timeZoneRemainder); + } + } + + for (int i = 0; i < formattedString.size() + 1; ++i) { + pszDateTime[i] = formattedString.c_str()[i]; + } + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + Kernel::OrbisKernelTimezone timeZone; + Kernel::sceKernelGettimezone(&timeZone); + + return sceRtcFormatRFC2822(pszDateTime, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); } -int PS4_SYSV_ABI sceRtcFormatRFC3339() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int iTimeZoneMinutes) { + LOG_TRACE(Lib_Rtc, "called"); + return sceRtcFormatRFC3339Precise(pszDateTime, pTickUtc, iTimeZoneMinutes); } -int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + Kernel::OrbisKernelTimezone timeZone; + Kernel::sceKernelGettimezone(&timeZone); + + return sceRtcFormatRFC3339(pszDateTime, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); } -int PS4_SYSV_ABI sceRtcFormatRFC3339Precise() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339Precise(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int iTimeZoneMinutes) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + OrbisRtcTick formatTick; + + if (pTickUtc == nullptr) { + sceRtcGetCurrentTick(&formatTick); + } else { + formatTick.tick = pTickUtc->tick; + } + + sceRtcTickAddMinutes(&formatTick, &formatTick, iTimeZoneMinutes); + + OrbisRtcDateTime formatTime; + + sceRtcSetTick(&formatTime, &formatTick); + + std::string formattedString; + formattedString = std::to_string(formatTime.year) + "-"; + + if (formatTime.month < 10) { + formattedString += "0" + std::to_string(formatTime.month) + "-"; + } else { + formattedString += std::to_string(formatTime.month) + "-"; + } + + if (formatTime.day < 10) { + formattedString += "0" + std::to_string(formatTime.day) + "T"; + } else { + formattedString += std::to_string(formatTime.day) + "T"; + } + + if (formatTime.hour < 10) { + formattedString += "0" + std::to_string(formatTime.hour) + ":"; + } else { + formattedString += std::to_string(formatTime.hour) + ":"; + } + + if (formatTime.minute < 10) { + formattedString += "0" + std::to_string(formatTime.minute) + ":"; + } else { + formattedString += std::to_string(formatTime.minute) + ":"; + } + + if (formatTime.second < 10) { + formattedString += "0" + std::to_string(formatTime.second); + } else { + formattedString += std::to_string(formatTime.second); + } + + if (formatTime.microsecond != 0) { + formattedString += "." + std::to_string(formatTime.microsecond / 1000).substr(0, 2); + } else { + formattedString += ".00"; + } + + if (iTimeZoneMinutes == 0) { + formattedString += "Z"; + } else { + int timeZoneHours = iTimeZoneMinutes / 60; + int timeZoneRemainder = iTimeZoneMinutes % 60; + + if (timeZoneHours < 0) { + formattedString += "-"; + timeZoneHours *= -1; + } else { + formattedString += "+"; + } + + if (timeZoneHours < 10) { + formattedString += "0" + std::to_string(timeZoneHours); + } else { + formattedString += std::to_string(timeZoneHours); + } + + if (timeZoneRemainder == 0) { + formattedString += ":00"; + } else { + if (timeZoneRemainder < 0) + timeZoneRemainder *= -1; + formattedString += ":" + std::to_string(timeZoneRemainder); + } + } + + for (int i = 0; i < formattedString.size() + 1; ++i) { + pszDateTime[i] = formattedString.c_str()[i]; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime(char* pszDateTime, + const OrbisRtcTick* pTickUtc) { + LOG_TRACE(Lib_Rtc, "called"); + + Kernel::OrbisKernelTimezone timeZone; + Kernel::sceKernelGettimezone(&timeZone); + + return sceRtcFormatRFC3339Precise(pszDateTime, pTickUtc, + -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60))); } -int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetCurrentClock() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentClock(OrbisRtcDateTime* pTime, int timeZone) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + OrbisRtcTick clockTick; + clockTick.tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + + sceRtcTickAddMinutes(&clockTick, &clockTick, timeZone); + sceRtcSetTick(pTime, &clockTick); + } + + return returnValue; } -int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime(OrbisRtcDateTime* pTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED; + + Kernel::OrbisKernelTimezone timeZone; + int returnValue = Kernel::sceKernelGettimezone(&timeZone); + + if (returnValue >= 0) { + Kernel::OrbisKernelTimespec clocktime; + + // calculate total timezone offset for converting UTC to local time + uint64_t tzOffset = -(timeZone.tz_minuteswest - (timeZone.tz_dsttime * 60)); + + if (returnValue >= 0) { + OrbisRtcTick newTick; + sceRtcGetCurrentTick(&newTick); + sceRtcTickAddMinutes(&newTick, &newTick, tzOffset); + sceRtcSetTick(pTime, &newTick); + } + } + + return returnValue; } -int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick(OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue == SCE_OK) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } else { + return ORBIS_RTC_ERROR_NOT_INITIALIZED; + } + + return SCE_OK; } int PS4_SYSV_ABI sceRtcGetCurrentTick(OrbisRtcTick* pTick) { - pTick->tick = std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count(); - return ORBIS_OK; + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick == nullptr) + return ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED; + + Kernel::OrbisKernelTimespec clocktime; + int returnValue = Kernel::sceKernelClockGettime(Kernel::ORBIS_CLOCK_REALTIME, &clocktime); + + if (returnValue >= 0) { + pTick->tick = clocktime.tv_nsec / 1000 + clocktime.tv_sec * 1000000 + UNIX_EPOCH_TICKS; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetDayOfWeek() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetDayOfWeek(int year, int month, int day) { + LOG_TRACE(Lib_Rtc, "called"); + + int sdk_version = 0; + int sdkResult = Kernel::sceKernelGetCompiledSdkVersion(&sdk_version); + if (sdkResult != ORBIS_OK) { + sdk_version = 0; + } + + if (sdk_version < 0x3000000) { + if (year < 1) { + return ORBIS_RTC_ERROR_INVALID_YEAR; + } + if (month > 12 || month <= 0) { + return ORBIS_RTC_ERROR_INVALID_MONTH; + } + } else { + if (year > 9999 || year < 1) { + return ORBIS_RTC_ERROR_INVALID_YEAR; + } + if (month > 12 || month <= 0) { + return ORBIS_RTC_ERROR_INVALID_MONTH; + } + } + + int daysInMonth = sceRtcGetDaysInMonth(year, month); + + if (day <= 0 || day > daysInMonth) + return ORBIS_RTC_ERROR_INVALID_DAY; + + std::chrono::sys_days chrono_time{std::chrono::year(year) / std::chrono::month(month) / + std::chrono::day(day)}; + std::chrono::weekday chrono_weekday{chrono_time}; + + return chrono_weekday.c_encoding(); } -int PS4_SYSV_ABI sceRtcGetDaysInMonth() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetDaysInMonth(int year, int month) { + LOG_TRACE(Lib_Rtc, "called"); + + if (year <= 0) + return ORBIS_RTC_ERROR_INVALID_YEAR; + + if (month <= 0 || month > 12) + return ORBIS_RTC_ERROR_INVALID_MONTH; + + std::chrono::year chronoYear = std::chrono::year(year); + std::chrono::month chronoMonth = std::chrono::month(month); + int lastDay = static_cast(unsigned( + std::chrono::year_month_day_last{chronoYear / chronoMonth / std::chrono::last}.day())); + + return lastDay; } -int PS4_SYSV_ABI sceRtcGetDosTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetDosTime(OrbisRtcDateTime* pTime, unsigned int* dosTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || dosTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isValid = sceRtcCheckValid(pTime); + if (isValid != SCE_OK) { + return isValid; + } + + *dosTime |= (pTime->second / 2) & 0x1F; + *dosTime |= (pTime->minute & 0x3F) << 5; + *dosTime |= (pTime->hour & 0x1F) << 11; + *dosTime |= (pTime->day & 0x1F) << 16; + *dosTime |= (pTime->month & 0x0F) << 21; + *dosTime |= ((pTime->year - 1980) & 0x7F) << 25; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isTimeValid = sceRtcCheckValid(pTime); + if (isTimeValid != 0) + return isTimeValid; + + if (pTime->month > 2) { + pTime->month -= 3; + } else { + pTime->month += 9; + pTime->year -= 1; + } + + int c = pTime->year / 100; + int ya = pTime->year - 100 * c; + + u64 days; + u64 msec; + + days = ((146097 * c) >> 2) + ((1461 * ya) >> 2) + (153 * pTime->month + 2) / 5 + pTime->day; + days -= 307; + days *= 86400000000; + + msec = pTime->hour * 3600000000 + pTime->minute * 60000000 + pTime->second * 1000000 + + pTime->microsecond; + + pTick->tick = days + msec; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetTickResolution() { +unsigned int PS4_SYSV_ABI sceRtcGetTickResolution() { + LOG_TRACE(Lib_Rtc, "called"); + return 1000000; } -int PS4_SYSV_ABI sceRtcGetTime_t() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetTime_t(OrbisRtcDateTime* pTime, time_t* llTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || llTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isValid = sceRtcCheckValid(pTime); + if (isValid != SCE_OK) { + return isValid; + } + + OrbisRtcTick timeTick; + sceRtcGetTick(pTime, &timeTick); + + if (timeTick.tick < UNIX_EPOCH_TICKS) { + *llTime = 0; + } else { + *llTime = (timeTick.tick - UNIX_EPOCH_TICKS) / 1000000; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcGetWin32FileTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcGetWin32FileTime(OrbisRtcDateTime* pTime, uint64_t* ulWin32Time) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || ulWin32Time == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int isValid = sceRtcCheckValid(pTime); + if (isValid != SCE_OK) { + return isValid; + } + + OrbisRtcTick timeTick; + sceRtcGetTick(pTime, &timeTick); + + if (timeTick.tick < WIN32_FILETIME_EPOCH_TICKS) { + *ulWin32Time = 0; + } else { + *ulWin32Time = (timeTick.tick - WIN32_FILETIME_EPOCH_TICKS) * 10; + } + + return SCE_OK; } int PS4_SYSV_ABI sceRtcInit() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; + return SCE_OK; } -int PS4_SYSV_ABI sceRtcIsLeapYear() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcIsLeapYear(int yearInt) { + LOG_TRACE(Lib_Rtc, "called"); + + if (yearInt < 1) + return ORBIS_RTC_ERROR_INVALID_YEAR; + + using namespace std::chrono; + + year_month_day_last ymdl{year(yearInt) / February / last}; + return (ymdl.day() == 29d); } -int PS4_SYSV_ABI sceRtcParseDateTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int GetMonthFromString(std::string monthStr) { + if (monthStr == "Jan") + return 1; + + if (monthStr == "Feb") + return 2; + + if (monthStr == "Mar") + return 3; + + if (monthStr == "Apr") + return 4; + + if (monthStr == "May") + return 5; + + if (monthStr == "Jun") + return 6; + + if (monthStr == "Jul") + return 7; + + if (monthStr == "Aug") + return 8; + + if (monthStr == "Sep") + return 9; + + if (monthStr == "Oct") + return 10; + + if (monthStr == "Nov") + return 11; + + if (monthStr == "Dec") + return 12; + + return 1; } -int PS4_SYSV_ABI sceRtcParseRFC3339() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcParseDateTime(OrbisRtcTick* pTickUtc, const char* pszDateTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickUtc == nullptr || pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + std::string dateTimeString = std::string(pszDateTime); + + char formatKey = dateTimeString[22]; + OrbisRtcDateTime dateTime; + + if (formatKey == 'Z' || formatKey == '-' || formatKey == '+') { + // RFC3339 + sceRtcParseRFC3339(pTickUtc, pszDateTime); + } else if (formatKey == ':') { + // RFC2822 + dateTime.day = std::stoi(dateTimeString.substr(5, 2)); + dateTime.month = GetMonthFromString(dateTimeString.substr(8, 3)); + dateTime.year = std::stoi(dateTimeString.substr(12, 4)); + dateTime.hour = std::stoi(dateTimeString.substr(17, 2)); + dateTime.minute = std::stoi(dateTimeString.substr(20, 2)); + dateTime.second = std::stoi(dateTimeString.substr(23, 2)); + dateTime.microsecond = 0; + + sceRtcGetTick(&dateTime, pTickUtc); + + if (dateTimeString[26] == '+') { + int timeZoneOffset = std::stoi(dateTimeString.substr(27, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(29, 2)); + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } else if (dateTimeString[26] == '-') { + int timeZoneOffset = std::stoi(dateTimeString.substr(27, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(29, 2)); + timeZoneOffset *= -1; + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } + + } else { + // asctime + dateTime.month = GetMonthFromString(dateTimeString.substr(4, 3)); + dateTime.day = std::stoi(dateTimeString.substr(8, 2)); + dateTime.hour = std::stoi(dateTimeString.substr(11, 2)); + dateTime.minute = std::stoi(dateTimeString.substr(14, 2)); + dateTime.second = std::stoi(dateTimeString.substr(17, 2)); + dateTime.year = std::stoi(dateTimeString.substr(20, 4)); + dateTime.microsecond = 0; + + sceRtcGetTick(&dateTime, pTickUtc); + } + + return SCE_OK; +} + +int PS4_SYSV_ABI sceRtcParseRFC3339(OrbisRtcTick* pTickUtc, const char* pszDateTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTickUtc == nullptr || pszDateTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + std::string dateTimeString = std::string(pszDateTime); + + OrbisRtcDateTime dateTime; + dateTime.year = std::stoi(dateTimeString.substr(0, 4)); + dateTime.month = std::stoi(dateTimeString.substr(5, 2)); + dateTime.day = std::stoi(dateTimeString.substr(8, 2)); + dateTime.hour = std::stoi(dateTimeString.substr(11, 2)); + dateTime.minute = std::stoi(dateTimeString.substr(14, 2)); + dateTime.second = std::stoi(dateTimeString.substr(17, 2)); + dateTime.microsecond = std::stoi(dateTimeString.substr(20, 2)); + + sceRtcGetTick(&dateTime, pTickUtc); + + if (dateTimeString[22] != 'Z') { + if (dateTimeString[22] == '-') { + int timeZoneOffset = std::stoi(dateTimeString.substr(23, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(26, 2)); + timeZoneOffset *= -1; + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } else if (dateTimeString[22] == '+') { + int timeZoneOffset = std::stoi(dateTimeString.substr(23, 2)) * 60; + timeZoneOffset += std::stoi(dateTimeString.substr(26, 2)); + sceRtcTickAddMinutes(pTickUtc, pTickUtc, timeZoneOffset); + } + } + + return SCE_OK; } int PS4_SYSV_ABI sceRtcSetConf() { @@ -162,89 +833,294 @@ int PS4_SYSV_ABI sceRtcSetConf() { return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick() { +int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick() { +int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick() { +int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetCurrentTick() { +int PS4_SYSV_ABI sceRtcSetCurrentTick(OrbisRtcTick* pTick) { LOG_ERROR(Lib_Rtc, "(STUBBED) called"); return ORBIS_OK; } -int PS4_SYSV_ABI sceRtcSetDosTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetDosTime(OrbisRtcDateTime* pTime, u32 dosTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTime->microsecond = 0; + pTime->second = (dosTime << 1) & 0x3e; + pTime->minute = (dosTime >> 5) & 0x3f; + pTime->hour = (dosTime & 0xf800) >> 0xb; + + int16_t days = dosTime >> 0x10; + + pTime->day = days & 0x1f; + pTime->month = (days >> 5) & 0x0f; + pTime->year = (days >> 9) + 1980; + return SCE_OK; } -int PS4_SYSV_ABI sceRtcSetTick() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr || pTick == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + u32 ly, ld, lm, j; + u64 days, msec; + + days = pTick->tick / 86400000000; + msec = pTick->tick % 86400000000; + + days += 307; + + j = (days << 2) - 1; + ly = j / 146097; + + j -= (146097 * ly); + ld = j >> 2; + + j = ((ld << 2) + 3) / 1461; + ld = (((ld << 2) + 7) - 1461 * j) >> 2; + + lm = (5 * ld - 3) / 153; + ld = (5 * ld + 2 - 153 * lm) / 5; + ly = 100 * ly + j; + + if (lm < 10) { + lm += 3; + } else { + lm -= 9; + ly++; + } + + pTime->year = ly; + pTime->month = lm; + pTime->day = ld; + + pTime->hour = msec / 3600000000; + msec %= 3600000000; + pTime->minute = msec / 60000000; + msec %= 60000000; + pTime->second = msec / 1000000; + msec %= 1000000; + pTime->microsecond = msec; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcSetTime_t() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetTime_t(OrbisRtcDateTime* pTime, time_t llTime) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + int sdk_version; + int sdkResult = Kernel::sceKernelGetCompiledSdkVersion(&sdk_version); + if (sdkResult != ORBIS_OK) { + sdk_version = 0; + } + + OrbisRtcTick newTick; + if (sdk_version < 0x3000000) { + newTick.tick = (llTime & 0xffffffff) * 1000000; + } else { + if (llTime < 0) { + return ORBIS_RTC_ERROR_INVALID_VALUE; + } + newTick.tick = llTime * 1000000; + } + + newTick.tick += UNIX_EPOCH_TICKS; + sceRtcSetTick(pTime, &newTick); + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcSetWin32FileTime() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcSetWin32FileTime(OrbisRtcDateTime* pTime, int64_t ulWin32Time) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTime == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + u64 convertedTime = (ulWin32Time / 10) + WIN32_FILETIME_EPOCH_TICKS; + + OrbisRtcTick convertedTick; + convertedTick.tick = convertedTime; + + sceRtcSetTick(pTime, &convertedTick); + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddDays() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddDays(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 86400000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddHours() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddHours(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 3600000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddMicroseconds() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddMicroseconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, + int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = lAdd + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddMinutes() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddMinutes(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 60000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddMonths() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddMonths(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + if (lAdd == 0) { + pTick1->tick = pTick2->tick; + return SCE_OK; + } + + OrbisRtcDateTime time; + s64 s; + s64 tempMonth; + + sceRtcSetTick(&time, pTick1); + + if (lAdd >= 0) { + s = 1; + } else { + s = -1; + } + + time.year += (lAdd / 12); + tempMonth = time.month + (lAdd % 12) - 1; + + if (tempMonth > 11 || tempMonth < 0) { + tempMonth -= s * 12; + time.year += s; + } + + time.month = tempMonth + 1; + + using namespace std::chrono; + year chronoYear = year(time.year); + month chronoMonth = month(time.month); + int lastDay = + static_cast(unsigned(year_month_day_last{chronoYear / chronoMonth / last}.day())); + + if (time.day > lastDay) { + time.day = lastDay; + } + + int timeIsValid = sceRtcCheckValid(&time); + if (timeIsValid == SCE_OK) { + sceRtcGetTick(&time, pTick1); + } else { + return timeIsValid; + } + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddSeconds() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddSeconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 1000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddTicks() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddTicks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = lAdd + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddWeeks() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddWeeks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + pTick1->tick = (lAdd * 604800000000) + pTick2->tick; + + return SCE_OK; } -int PS4_SYSV_ABI sceRtcTickAddYears() { - LOG_ERROR(Lib_Rtc, "(STUBBED) called"); - return ORBIS_OK; +int PS4_SYSV_ABI sceRtcTickAddYears(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd) { + LOG_TRACE(Lib_Rtc, "called"); + + if (pTick1 == nullptr || pTick2 == nullptr) + return ORBIS_RTC_ERROR_INVALID_POINTER; + + OrbisRtcDateTime time; + + if (lAdd == 0) { + pTick1->tick = pTick2->tick; + return SCE_OK; + } + + sceRtcSetTick(&time, pTick1); + + time.year += lAdd; + + int timeIsValid = sceRtcCheckValid(&time); + if (timeIsValid == SCE_OK) { + sceRtcGetTick(&time, pTick1); + } else { + return timeIsValid; + } + + return SCE_OK; } void RegisterlibSceRtc(Core::Loader::SymbolsResolver* sym) { diff --git a/src/core/libraries/rtc/rtc.h b/src/core/libraries/rtc/rtc.h index ee6afa70..c4104086 100644 --- a/src/core/libraries/rtc/rtc.h +++ b/src/core/libraries/rtc/rtc.h @@ -11,57 +11,81 @@ class SymbolsResolver; namespace Libraries::Rtc { +constexpr int ORBIS_RTC_DAYOFWEEK_SUNDAY = 0; +constexpr int ORBIS_RTC_DAYOFWEEK_MONDAY = 1; +constexpr int ORBIS_RTC_DAYOFWEEK_TUESDAY = 2; +constexpr int ORBIS_RTC_DAYOFWEEK_WEDNESDAY = 3; +constexpr int ORBIS_RTC_DAYOFWEEK_THURSDAY = 4; +constexpr int ORBIS_RTC_DAYOFWEEK_FRIDAY = 5; +constexpr int ORBIS_RTC_DAYOFWEEK_SATURDAY = 6; + +constexpr int64_t UNIX_EPOCH_TICKS = 0xdcbffeff2bc000; +constexpr int64_t WIN32_FILETIME_EPOCH_TICKS = 0xb36168b6a58000; + struct OrbisRtcTick { - u64 tick; + uint64_t tick; }; -int PS4_SYSV_ABI sceRtcCheckValid(); -int PS4_SYSV_ABI sceRtcCompareTick(); -int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc(); -int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime(); +struct OrbisRtcDateTime { + uint16_t year; + uint16_t month; + uint16_t day; + uint16_t hour; + uint16_t minute; + uint16_t second; + uint32_t microsecond; +}; + +int PS4_SYSV_ABI sceRtcCheckValid(OrbisRtcDateTime* pTime); +int PS4_SYSV_ABI sceRtcCompareTick(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2); +int PS4_SYSV_ABI sceRtcConvertLocalTimeToUtc(OrbisRtcTick* pTickLocal, OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcConvertUtcToLocalTime(OrbisRtcTick* pTickUtc, OrbisRtcTick* pTickLocal); int PS4_SYSV_ABI sceRtcEnd(); -int PS4_SYSV_ABI sceRtcFormatRFC2822(); -int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime(); -int PS4_SYSV_ABI sceRtcFormatRFC3339(); -int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime(); -int PS4_SYSV_ABI sceRtcFormatRFC3339Precise(); -int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime(); -int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick(); -int PS4_SYSV_ABI sceRtcGetCurrentClock(); -int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime(); -int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick(); -int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick(); -int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick(); +int PS4_SYSV_ABI sceRtcFormatRFC2822(char* pszDateTime, const OrbisRtcTick* pTickUtc, int minutes); +int PS4_SYSV_ABI sceRtcFormatRFC2822LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcFormatRFC3339(char* pszDateTime, const OrbisRtcTick* pTickUtc, int minutes); +int PS4_SYSV_ABI sceRtcFormatRFC3339LocalTime(char* pszDateTime, const OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcFormatRFC3339Precise(char* pszDateTime, const OrbisRtcTick* pTickUtc, + int minutes); +int PS4_SYSV_ABI sceRtcFormatRFC3339PreciseLocalTime(char* pszDateTime, + const OrbisRtcTick* pTickUtc); +int PS4_SYSV_ABI sceRtcGetCurrentAdNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcGetCurrentClock(OrbisRtcDateTime* pTime, int timeZone); +int PS4_SYSV_ABI sceRtcGetCurrentClockLocalTime(OrbisRtcDateTime* pTime); +int PS4_SYSV_ABI sceRtcGetCurrentDebugNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcGetCurrentNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcGetCurrentRawNetworkTick(OrbisRtcTick* pTick); int PS4_SYSV_ABI sceRtcGetCurrentTick(OrbisRtcTick* pTick); -int PS4_SYSV_ABI sceRtcGetDayOfWeek(); -int PS4_SYSV_ABI sceRtcGetDaysInMonth(); -int PS4_SYSV_ABI sceRtcGetDosTime(); -int PS4_SYSV_ABI sceRtcGetTick(); -int PS4_SYSV_ABI sceRtcGetTickResolution(); -int PS4_SYSV_ABI sceRtcGetTime_t(); -int PS4_SYSV_ABI sceRtcGetWin32FileTime(); +int PS4_SYSV_ABI sceRtcGetDayOfWeek(int year, int month, int day); +int PS4_SYSV_ABI sceRtcGetDaysInMonth(int year, int month); +int PS4_SYSV_ABI sceRtcGetDosTime(OrbisRtcDateTime* pTime, unsigned int* dosTime); +int PS4_SYSV_ABI sceRtcGetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick); +unsigned int PS4_SYSV_ABI sceRtcGetTickResolution(); +int PS4_SYSV_ABI sceRtcGetTime_t(OrbisRtcDateTime* pTime, time_t* llTime); +int PS4_SYSV_ABI sceRtcGetWin32FileTime(OrbisRtcDateTime* pTime, uint64_t* ulWin32Time); int PS4_SYSV_ABI sceRtcInit(); -int PS4_SYSV_ABI sceRtcIsLeapYear(); -int PS4_SYSV_ABI sceRtcParseDateTime(); -int PS4_SYSV_ABI sceRtcParseRFC3339(); +int PS4_SYSV_ABI sceRtcIsLeapYear(int yearInt); +int PS4_SYSV_ABI sceRtcParseDateTime(OrbisRtcTick* pTickUtc, const char* pszDateTime); +int PS4_SYSV_ABI sceRtcParseRFC3339(OrbisRtcTick* pTickUtc, const char* pszDateTime); int PS4_SYSV_ABI sceRtcSetConf(); -int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick(); -int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick(); -int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick(); -int PS4_SYSV_ABI sceRtcSetCurrentTick(); -int PS4_SYSV_ABI sceRtcSetDosTime(); -int PS4_SYSV_ABI sceRtcSetTick(); -int PS4_SYSV_ABI sceRtcSetTime_t(); -int PS4_SYSV_ABI sceRtcSetWin32FileTime(); -int PS4_SYSV_ABI sceRtcTickAddDays(); -int PS4_SYSV_ABI sceRtcTickAddHours(); -int PS4_SYSV_ABI sceRtcTickAddMicroseconds(); -int PS4_SYSV_ABI sceRtcTickAddMinutes(); -int PS4_SYSV_ABI sceRtcTickAddMonths(); -int PS4_SYSV_ABI sceRtcTickAddSeconds(); -int PS4_SYSV_ABI sceRtcTickAddTicks(); -int PS4_SYSV_ABI sceRtcTickAddWeeks(); -int PS4_SYSV_ABI sceRtcTickAddYears(); +int PS4_SYSV_ABI sceRtcSetCurrentAdNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetCurrentDebugNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetCurrentNetworkTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetCurrentTick(OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetDosTime(OrbisRtcDateTime* pTime, u32 dosTime); +int PS4_SYSV_ABI sceRtcSetTick(OrbisRtcDateTime* pTime, OrbisRtcTick* pTick); +int PS4_SYSV_ABI sceRtcSetTime_t(OrbisRtcDateTime* pTime, time_t llTime); +int PS4_SYSV_ABI sceRtcSetWin32FileTime(OrbisRtcDateTime* pTime, int64_t ulWin32Time); +int PS4_SYSV_ABI sceRtcTickAddDays(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddHours(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddMicroseconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, + int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddMinutes(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddMonths(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddSeconds(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddTicks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int64_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddWeeks(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); +int PS4_SYSV_ABI sceRtcTickAddYears(OrbisRtcTick* pTick1, OrbisRtcTick* pTick2, int32_t lAdd); void RegisterlibSceRtc(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::Rtc \ No newline at end of file diff --git a/src/core/libraries/rtc/rtc_error.h b/src/core/libraries/rtc/rtc_error.h index 04eecbbd..3af5a68f 100644 --- a/src/core/libraries/rtc/rtc_error.h +++ b/src/core/libraries/rtc/rtc_error.h @@ -3,6 +3,7 @@ #pragma once +constexpr int ORBIS_RTC_ERROR_DATETIME_UNINITIALIZED = 0x7FFEF9FE; constexpr int ORBIS_RTC_ERROR_INVALID_PARAMETER = 0x80010602; constexpr int ORBIS_RTC_ERROR_INVALID_TICK_PARAMETER = 0x80010603; constexpr int ORBIS_RTC_ERROR_INVALID_DATE_PARAMETER = 0x80010604; @@ -14,4 +15,18 @@ constexpr int ORBIS_RTC_ERROR_INVALID_DAYS_PARAMETER = 0x80010623; constexpr int ORBIS_RTC_ERROR_INVALID_HOURS_PARAMETER = 0x80010624; constexpr int ORBIS_RTC_ERROR_INVALID_MINUTES_PARAMETER = 0x80010625; constexpr int ORBIS_RTC_ERROR_INVALID_SECONDS_PARAMETER = 0x80010626; -constexpr int ORBIS_RTC_ERROR_INVALID_MILLISECONDS_PARAMETER = 0x80010627; \ No newline at end of file +constexpr int ORBIS_RTC_ERROR_INVALID_MILLISECONDS_PARAMETER = 0x80010627; +constexpr int ORBIS_RTC_ERROR_NOT_INITIALIZED = 0x80B50001; +constexpr int ORBIS_RTC_ERROR_INVALID_POINTER = 0x80B50002; +constexpr int ORBIS_RTC_ERROR_INVALID_VALUE = 0x80B50003; +constexpr int ORBIS_RTC_ERROR_INVALID_ARG = 0x80B50004; +constexpr int ORBIS_RTC_ERROR_NOT_SUPPORTED = 0x80B50005; +constexpr int ORBIS_RTC_ERROR_NO_CLOCK = 0x80B50006; +constexpr int ORBIS_RTC_ERROR_BAD_PARSE = 0x80B50007; +constexpr int ORBIS_RTC_ERROR_INVALID_YEAR = 0x80B50008; +constexpr int ORBIS_RTC_ERROR_INVALID_MONTH = 0x80B50009; +constexpr int ORBIS_RTC_ERROR_INVALID_DAY = 0x80B5000A; +constexpr int ORBIS_RTC_ERROR_INVALID_HOUR = 0x80B5000B; +constexpr int ORBIS_RTC_ERROR_INVALID_MINUTE = 0x80B5000C; +constexpr int ORBIS_RTC_ERROR_INVALID_SECOND = 0x80B5000D; +constexpr int ORBIS_RTC_ERROR_INVALID_MICROSECOND = 0x80B5000E; \ No newline at end of file