2020-12-05 13:08:24 +01:00
# include "stdafx.h"
2016-03-21 20:43:03 +01:00
# include "Emu/Cell/PPUModule.h"
# include "cellRtc.h"
2020-04-09 14:54:41 +02:00
# include "Emu/Cell/lv2/sys_time.h"
# include "Emu/Cell/lv2/sys_memory.h"
# include "Emu/Cell/lv2/sys_ss.h"
2018-08-25 14:39:00 +02:00
LOG_CHANNEL ( cellRtc ) ;
2016-03-21 20:43:03 +01:00
2020-04-09 14:54:41 +02:00
template < >
void fmt_class_string < CellRtcError > : : format ( std : : string & out , u64 arg )
{
format_enum ( out , arg , [ ] ( auto error )
{
switch ( error )
{
STR_CASE ( CELL_RTC_ERROR_NOT_INITIALIZED ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_POINTER ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_VALUE ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_ARG ) ;
STR_CASE ( CELL_RTC_ERROR_NOT_SUPPORTED ) ;
STR_CASE ( CELL_RTC_ERROR_NO_CLOCK ) ;
STR_CASE ( CELL_RTC_ERROR_BAD_PARSE ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_YEAR ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_MONTH ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_DAY ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_HOUR ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_MINUTE ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_SECOND ) ;
STR_CASE ( CELL_RTC_ERROR_INVALID_MICROSECOND ) ;
}
return unknown ;
} ) ;
}
2024-04-20 15:41:42 +02:00
static inline char ascii ( u8 num )
{
return num + ' 0 ' ;
}
static inline s8 digit ( char c )
{
return c - ' 0 ' ;
}
2020-04-09 14:54:41 +02:00
static bool is_leap_year ( u32 year )
{
return year % 4 = = 0 & & ( year % 100 ! = 0 | | year % 400 = = 0 ) ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetCurrentTick ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . trace ( " cellRtcGetCurrentTick(pTick=*0x%x) " , pTick ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < s64 > sec ;
vm : : var < s64 > nsec ;
error_code ret = sys_time_get_current_time ( sec , nsec ) ;
2024-04-18 16:45:26 +02:00
if ( ret < CELL_OK )
2020-04-09 14:54:41 +02:00
{
return ret ;
}
pTick - > tick = * nsec / 1000 + * sec * cellRtcGetTickResolution ( ) + RTC_MAGIC_OFFSET ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetCurrentClock ( ppu_thread & ppu , vm : : ptr < CellRtcDateTime > pClock , s32 iTimeZone )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcGetCurrentClock(pClock=*0x%x, iTimeZone=%d) " , pClock , iTimeZone ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pClock . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , tick . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < s64 > sec ;
vm : : var < s64 > nsec ;
error_code ret = sys_time_get_current_time ( sec , nsec ) ;
2024-04-18 16:45:26 +02:00
if ( ret < CELL_OK )
2020-04-09 14:54:41 +02:00
{
return ret ;
}
tick - > tick = * nsec / 1000 + * sec * cellRtcGetTickResolution ( ) + RTC_MAGIC_OFFSET ;
2024-04-18 17:11:59 +02:00
cellRtcTickAddMinutes ( ppu , tick , tick , iTimeZone ) ;
cellRtcSetTick ( ppu , pClock , tick ) ;
2020-04-09 14:54:41 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetCurrentClockLocalTime ( ppu_thread & ppu , vm : : ptr < CellRtcDateTime > pClock )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . trace ( " cellRtcGetCurrentClockLocalTime(pClock=*0x%x) " , pClock ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pClock . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < s32 > timezone ;
vm : : var < s32 > summertime ;
error_code ret = sys_time_get_timezone ( timezone , summertime ) ;
2024-04-18 16:45:26 +02:00
if ( ret < CELL_OK )
2020-04-09 14:54:41 +02:00
{
return ret ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pClock . addr ( ) , page_attr ) ! = CELL_OK ) // Should always evaluate to false, already checked above
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , tick . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < s64 > sec ;
vm : : var < s64 > nsec ;
ret = sys_time_get_current_time ( sec , nsec ) ;
2024-04-18 16:45:26 +02:00
if ( ret < CELL_OK )
2020-04-09 14:54:41 +02:00
{
return ret ;
}
tick - > tick = * nsec / 1000 + * sec * cellRtcGetTickResolution ( ) + RTC_MAGIC_OFFSET ;
2024-04-18 17:11:59 +02:00
cellRtcTickAddMinutes ( ppu , tick , tick , * timezone + * summertime ) ;
cellRtcSetTick ( ppu , pClock , tick ) ;
2020-04-09 14:54:41 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcFormatRfc2822 ( ppu_thread & ppu , vm : : ptr < char > pszDateTime , vm : : cptr < CellRtcTick > pUtc , s32 iTimeZone )
2016-03-21 20:43:03 +01:00
{
2024-04-20 15:41:42 +02:00
cellRtc . notice ( " cellRtcFormatRfc2822(pszDateTime=*0x%x, pUtc=*0x%x, iTimeZone=%d) " , pszDateTime , pUtc , iTimeZone ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pszDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pUtc . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > rtc_tick ;
2024-04-20 15:41:42 +02:00
if ( ! pUtc ) // Should always evaluate to false, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
2024-04-18 17:11:59 +02:00
cellRtcGetCurrentTick ( ppu , rtc_tick ) ;
2020-04-09 14:54:41 +02:00
}
else
{
rtc_tick - > tick = pUtc - > tick ;
}
vm : : var < CellRtcDateTime > date_time ;
2024-04-18 17:11:59 +02:00
cellRtcTickAddMinutes ( ppu , rtc_tick , rtc_tick , iTimeZone ) ;
cellRtcSetTick ( ppu , date_time , rtc_tick ) ;
2020-04-09 14:54:41 +02:00
error_code ret = cellRtcCheckValid ( date_time ) ;
if ( ret ! = CELL_OK )
{
return ret ;
}
s32 weekdayIdx = cellRtcGetDayOfWeek ( date_time - > year , date_time - > month , date_time - > day ) ;
// Day name
2024-04-20 15:41:42 +02:00
pszDateTime [ 0 ] = std : : toupper ( WEEKDAY_NAMES [ weekdayIdx ] [ 0 ] ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 1 ] = WEEKDAY_NAMES [ weekdayIdx ] [ 1 ] ;
pszDateTime [ 2 ] = WEEKDAY_NAMES [ weekdayIdx ] [ 2 ] ;
pszDateTime [ 3 ] = ' , ' ;
pszDateTime [ 4 ] = ' ' ;
// Day number
2024-04-20 15:41:42 +02:00
pszDateTime [ 5 ] = ascii ( date_time - > day / 10 ) ;
pszDateTime [ 6 ] = ascii ( date_time - > day % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 7 ] = ' ' ;
// month name
2024-04-20 15:41:42 +02:00
pszDateTime [ 8 ] = std : : toupper ( MONTH_NAMES [ date_time - > month - 1 ] [ 0 ] ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 9 ] = MONTH_NAMES [ date_time - > month - 1 ] [ 1 ] ;
pszDateTime [ 10 ] = MONTH_NAMES [ date_time - > month - 1 ] [ 2 ] ;
pszDateTime [ 0xb ] = ' ' ;
// year
2024-04-20 15:41:42 +02:00
pszDateTime [ 0xc ] = ascii ( date_time - > year / 1000 ) ;
pszDateTime [ 0xd ] = ascii ( date_time - > year / 100 % 10 ) ;
pszDateTime [ 0xe ] = ascii ( date_time - > year / 10 % 10 ) ;
pszDateTime [ 0xf ] = ascii ( date_time - > year % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x10 ] = ' ' ;
// Hours
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x11 ] = ascii ( date_time - > hour / 10 ) ;
pszDateTime [ 0x12 ] = ascii ( date_time - > hour % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x13 ] = ' : ' ;
// Minutes
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x14 ] = ascii ( date_time - > minute / 10 ) ;
pszDateTime [ 0x15 ] = ascii ( date_time - > minute % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x16 ] = ' : ' ;
// Seconds
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x17 ] = ascii ( date_time - > second / 10 ) ;
pszDateTime [ 0x18 ] = ascii ( date_time - > second % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x19 ] = ' ' ;
// Timezone -/+
if ( iTimeZone < 0 )
{
2024-04-20 15:41:42 +02:00
iTimeZone = - iTimeZone ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x1a ] = ' - ' ;
}
else
{
pszDateTime [ 0x1a ] = ' + ' ;
}
2024-04-20 15:41:42 +02:00
const u32 time_zone_hours = iTimeZone / 60 % 100 ;
const u32 time_zone_minutes = iTimeZone % 60 ;
2020-04-09 14:54:41 +02:00
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x1b ] = ascii ( time_zone_hours / 10 ) ;
pszDateTime [ 0x1c ] = ascii ( time_zone_hours % 10 ) ;
pszDateTime [ 0x1d ] = ascii ( time_zone_minutes / 10 ) ;
pszDateTime [ 0x1e ] = ascii ( time_zone_minutes % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x1f ] = ' \0 ' ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcFormatRfc2822LocalTime ( ppu_thread & ppu , vm : : ptr < char > pszDateTime , vm : : cptr < CellRtcTick > pUtc )
2016-03-21 20:43:03 +01:00
{
2024-04-20 15:41:42 +02:00
cellRtc . notice ( " cellRtcFormatRfc2822LocalTime(pszDateTime=*0x%x, pUtc=*0x%x) " , pszDateTime , pUtc ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pszDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pUtc . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < s32 > timezone ;
vm : : var < s32 > summertime ;
error_code ret = sys_time_get_timezone ( timezone , summertime ) ;
2024-04-18 16:45:26 +02:00
if ( ret < CELL_OK )
2020-04-09 14:54:41 +02:00
{
return ret ;
}
2024-04-18 17:11:59 +02:00
return cellRtcFormatRfc2822 ( ppu , pszDateTime , pUtc , * timezone + * summertime ) ;
2016-03-21 20:43:03 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcFormatRfc3339 ( ppu_thread & ppu , vm : : ptr < char > pszDateTime , vm : : cptr < CellRtcTick > pUtc , s32 iTimeZone )
2016-03-21 20:43:03 +01:00
{
2024-04-20 15:41:42 +02:00
cellRtc . notice ( " cellRtcFormatRfc3339(pszDateTime=*0x%x, pUtc=*0x%x, iTimeZone=%d) " , pszDateTime , pUtc , iTimeZone ) ;
2018-08-25 14:39:00 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pszDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pUtc . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > rtc_tick ;
2024-04-20 15:41:42 +02:00
if ( ! pUtc ) // Should always evaluate to false, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
2024-04-18 17:11:59 +02:00
cellRtcGetCurrentTick ( ppu , rtc_tick ) ;
2020-04-09 14:54:41 +02:00
}
else
{
rtc_tick - > tick = pUtc - > tick ;
}
vm : : var < CellRtcDateTime > date_time ;
2024-04-18 17:11:59 +02:00
cellRtcTickAddMinutes ( ppu , rtc_tick , rtc_tick , iTimeZone ) ;
cellRtcSetTick ( ppu , date_time , rtc_tick ) ;
2020-04-09 14:54:41 +02:00
error_code ret = cellRtcCheckValid ( date_time ) ;
if ( ret ! = CELL_OK )
{
return ret ;
}
// Year - XXXX-04-13T10:56:31.35+66:40
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x0 ] = ascii ( date_time - > year / 1000 ) ;
pszDateTime [ 0x1 ] = ascii ( date_time - > year / 100 % 10 ) ;
pszDateTime [ 0x2 ] = ascii ( date_time - > year / 10 % 10 ) ;
pszDateTime [ 0x3 ] = ascii ( date_time - > year % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x4 ] = ' - ' ;
// Month - 2020-XX-13T10:56:31.35+66:40
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x5 ] = ascii ( date_time - > month / 10 ) ;
pszDateTime [ 0x6 ] = ascii ( date_time - > month % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x7 ] = ' - ' ;
// Day - 2020-04-XXT10:56:31.35+66:40
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x8 ] = ascii ( date_time - > day / 10 ) ;
pszDateTime [ 0x9 ] = ascii ( date_time - > day % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0xa ] = ' T ' ;
// Hours - 2020-04-13TXX:56:31.35+66:40
2024-04-20 15:41:42 +02:00
pszDateTime [ 0xb ] = ascii ( date_time - > hour / 10 ) ;
pszDateTime [ 0xc ] = ascii ( date_time - > hour % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0xd ] = ' : ' ;
// Minutes - 2020-04-13T10:XX:31.35+66:40
2024-04-20 15:41:42 +02:00
pszDateTime [ 0xe ] = ascii ( date_time - > minute / 10 ) ;
pszDateTime [ 0xf ] = ascii ( date_time - > minute % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x10 ] = ' : ' ;
// Seconds - 2020-04-13T10:56:XX.35+66:40
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x11 ] = ascii ( date_time - > second / 10 ) ;
pszDateTime [ 0x12 ] = ascii ( date_time - > second % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x13 ] = ' . ' ;
2024-04-20 15:41:42 +02:00
// Hundredths of a second - 2020-04-13T10:56:31.XX+66:40
pszDateTime [ 0x14 ] = ascii ( date_time - > microsecond / 100'000 ) ;
pszDateTime [ 0x15 ] = ascii ( date_time - > microsecond / 10'000 % 10 ) ;
2020-04-09 14:54:41 +02:00
2024-04-20 15:41:42 +02:00
// Time zone - 'Z' for UTC
2020-04-09 14:54:41 +02:00
if ( iTimeZone = = 0 )
{
pszDateTime [ 0x16 ] = ' Z ' ;
pszDateTime [ 0x17 ] = ' \0 ' ;
}
2024-04-20 15:41:42 +02:00
// Time zone - ±hh:mm
2020-04-09 14:54:41 +02:00
else
{
if ( iTimeZone < 0 )
{
2024-04-20 15:41:42 +02:00
iTimeZone = - iTimeZone ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x16 ] = ' - ' ;
}
else
{
pszDateTime [ 0x16 ] = ' + ' ;
}
2024-04-20 15:41:42 +02:00
const u32 time_zone_hours = iTimeZone / 60 % 100 ;
const u32 time_zone_minutes = iTimeZone % 60 ;
pszDateTime [ 0x17 ] = ascii ( time_zone_hours / 10 ) ;
pszDateTime [ 0x18 ] = ascii ( time_zone_hours % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x19 ] = ' : ' ;
2024-04-20 15:41:42 +02:00
pszDateTime [ 0x1a ] = ascii ( time_zone_minutes / 10 ) ;
pszDateTime [ 0x1b ] = ascii ( time_zone_minutes % 10 ) ;
2020-04-09 14:54:41 +02:00
pszDateTime [ 0x1c ] = ' \0 ' ;
}
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcFormatRfc3339LocalTime ( ppu_thread & ppu , vm : : ptr < char > pszDateTime , vm : : cptr < CellRtcTick > pUtc )
2016-03-21 20:43:03 +01:00
{
2024-04-20 15:41:42 +02:00
cellRtc . notice ( " cellRtcFormatRfc3339LocalTime(pszDateTime=*0x%x, pUtc=*0x%x) " , pszDateTime , pUtc ) ;
2018-08-25 14:39:00 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pszDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pUtc . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < s32 > timezone ;
vm : : var < s32 > summertime ;
error_code ret = sys_time_get_timezone ( timezone , summertime ) ;
2024-04-18 16:45:26 +02:00
if ( ret < CELL_OK )
2020-04-09 14:54:41 +02:00
{
return ret ;
}
2024-04-18 17:11:59 +02:00
return cellRtcFormatRfc3339 ( ppu , pszDateTime , pUtc , * timezone + * summertime ) ;
2016-03-21 20:43:03 +01:00
}
2024-04-20 15:41:42 +02:00
u16 rtcParseComponent ( vm : : cptr < char > pszDateTime , u32 & pos , char delimiter , const char * component_name )
{
if ( delimiter ! = 0 )
{
if ( pszDateTime [ pos ] ! = delimiter )
{
cellRtc . error ( " rtcParseComponent(): failed to parse %s: invalid or missing delimiter " , component_name ) ;
return umax ;
}
pos + + ;
}
if ( ! std : : isdigit ( pszDateTime [ pos ] ) )
{
cellRtc . error ( " rtcParseComponent(): failed to parse %s: ASCII value 0x%x at position %d is not a digit " , component_name , pszDateTime [ pos + 1 ] , pos ) ;
return umax ;
}
u16 ret = digit ( pszDateTime [ pos ] ) ;
pos + + ;
if ( std : : isdigit ( pszDateTime [ pos ] ) )
{
ret = ret * 10 + digit ( pszDateTime [ pos ] ) ;
pos + + ;
}
return ret ;
}
template < usz size >
u8 rtcParseName ( vm : : cptr < char > pszDateTime , u32 & pos , const std : : array < std : : string_view , size > & names , bool allow_short_name = true )
{
for ( u8 name_idx = 0 ; name_idx < names . size ( ) ; name_idx + + )
{
const u32 name_length = static_cast < u32 > ( names [ name_idx ] . length ( ) ) ;
u32 ch_idx = 0 ;
while ( ch_idx < name_length & & std : : tolower ( pszDateTime [ pos + ch_idx ] ) = = names [ name_idx ] [ ch_idx ] ) // Not case sensitive
{
ch_idx + + ;
}
if ( ch_idx = = name_length ) // Full name matched
{
pos + = name_length ;
return name_idx ;
}
if ( allow_short_name & & ch_idx > = 3 ) // Short name matched
{
pos + = 3 ; // Only increment by 3, even if more letters were matched
return name_idx ;
}
}
return size ;
}
2024-04-18 17:11:59 +02:00
error_code rtcParseRfc2822 ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pUtc , vm : : cptr < char > pszDateTime , u32 pos )
2024-04-20 15:41:42 +02:00
{
// Day: "X" or "XX"
const u16 day = rtcParseComponent ( pszDateTime , pos , 0 , " day " ) ;
if ( day = = umax )
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
// Mandatory space or hyphen
if ( pszDateTime [ pos ] ! = ' ' & & pszDateTime [ pos ] ! = ' - ' )
{
return { CELL_RTC_ERROR_BAD_PARSE , " rtcParseRfc2822(): invalid or missing delimiter after day " } ;
}
pos + + ;
// Month: at least the first three letters
const u16 month = rtcParseName ( pszDateTime , pos , MONTH_NAMES ) + 1 ;
if ( month > MONTH_NAMES . size ( ) ) // No match
{
return { CELL_RTC_ERROR_BAD_PARSE , " rtcParseRfc2822(): failed to parse month: string at position %d doesn't match any name " , pos } ;
}
// Mandatory space or hyphen
if ( pszDateTime [ pos ] ! = ' ' & & pszDateTime [ pos ] ! = ' - ' )
{
return { CELL_RTC_ERROR_BAD_PARSE , " rtcParseRfc2822(): invalid or missing delimiter after month " } ;
}
pos + + ;
// Year: "XX" or "XXXX"
u16 year = 0 ;
if ( ! std : : isdigit ( pszDateTime [ pos ] ) | |
! std : : isdigit ( pszDateTime [ pos + 1 ] ) )
{
return { CELL_RTC_ERROR_BAD_PARSE , " rtcParseRfc2822(): failed to parse year: one of the first two ASCII values 0x%x, 0x%x at position %d is not a digit " ,
pszDateTime [ pos ] , pszDateTime [ pos + 1 ] , pos } ;
}
if ( ! std : : isdigit ( pszDateTime [ pos + 2 ] ) | |
! std : : isdigit ( pszDateTime [ pos + 3 ] ) )
{
year = digit ( pszDateTime [ pos ] ) * 10 + digit ( pszDateTime [ pos + 1 ] ) ;
year + = ( year < 50 ) ? 2000 : 1900 ;
pos + = 2 ;
}
else
{
year = digit ( pszDateTime [ pos ] ) * 1000 + digit ( pszDateTime [ pos + 1 ] ) * 100 + digit ( pszDateTime [ pos + 2 ] ) * 10 + digit ( pszDateTime [ pos + 3 ] ) ;
pos + = 4 ;
}
// Hour: " X" or " XX"
const u16 hour = rtcParseComponent ( pszDateTime , pos , ' ' , " hour " ) ;
if ( hour = = umax )
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
if ( hour > 25 ) // LLE uses 25
{
return { CELL_RTC_ERROR_BAD_PARSE , " rtcParseRfc2822(): failed to parse hour: hour greater than 25 " } ;
}
// Minute: ":X" or ":XX"
const u16 minute = rtcParseComponent ( pszDateTime , pos , ' : ' , " minute " ) ;
if ( minute = = umax )
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
// Second, optional: ":X" or ":XX"
// The string can't end with '\0' here, there must a space before it
u16 second = 0 ;
if ( pszDateTime [ pos ] ! = ' ' )
{
second = rtcParseComponent ( pszDateTime , pos , ' : ' , " second " ) ;
if ( second = = umax )
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
}
else
{
// If there are no seconds in the string, time zone requires two preceding spaces to be properly parsed
pos + + ;
}
// Time zone, optional, error if there is no valid time zone after the space
s32 time_zone = 0 ;
if ( pszDateTime [ pos ] = = ' ' )
{
pos + + ;
if ( pszDateTime [ pos ] = = ' + ' | | pszDateTime [ pos ] = = ' - ' )
{
// "±hhmm"
if ( std : : isdigit ( pszDateTime [ pos + 1 ] ) & &
std : : isdigit ( pszDateTime [ pos + 2 ] ) & &
std : : isdigit ( pszDateTime [ pos + 3 ] ) & &
std : : isdigit ( pszDateTime [ pos + 4 ] ) )
{
const s32 time_zone_hhmm = digit ( pszDateTime [ pos + 1 ] ) * 1000 + digit ( pszDateTime [ pos + 2 ] ) * 100 + digit ( pszDateTime [ pos + 3 ] ) * 10 + digit ( pszDateTime [ pos + 4 ] ) ;
time_zone = time_zone_hhmm / 100 * 60 + time_zone_hhmm % 60 ; // LLE uses % 60 instead of % 100
}
else
{
// No error, LLE does this for some reason
time_zone = - 1 ;
}
if ( pszDateTime [ pos ] = = ' - ' )
{
time_zone = - time_zone ;
}
}
else if ( pszDateTime [ pos ] ! = ' U ' & & pszDateTime [ pos + 1 ] ! = ' T ' ) // Case sensitive, should be || but LLE uses &&
{
// "GMT", "EST", "EDT", etc.
const u32 time_zone_idx = rtcParseName ( pszDateTime , pos , TIME_ZONE_NAMES , false ) ;
if ( time_zone_idx < TIME_ZONE_NAMES . size ( ) )
{
time_zone = TIME_ZONE_VALUES [ time_zone_idx ] * 30 ;
}
else
{
// Military time zones
// "A", "B", "C", ..., not case sensitive
// These are all off by one ("A" should be UTC+01:00, "B" should be UTC+02:00, etc.)
const char letter = std : : toupper ( pszDateTime [ pos ] ) ;
if ( letter > = ' A ' & & letter < = ' M ' & & letter ! = ' J ' )
{
time_zone = ( letter - ' A ' ) * 60 ;
}
else if ( letter > = ' N ' & & letter < = ' Y ' )
{
time_zone = ( ' N ' - letter ) * 60 ;
}
else if ( letter ! = ' Z ' )
{
return { CELL_RTC_ERROR_BAD_PARSE , " rtcParseRfc2822(): failed to parse time zone " } ;
}
}
}
}
const vm : : var < CellRtcDateTime > date_time { { year , month , day , hour , minute , second , 0 } } ;
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , date_time , pUtc ) ;
cellRtcTickAddMinutes ( ppu , pUtc , pUtc , - time_zone ) ; // The time zone value needs to be subtracted
2024-04-20 15:41:42 +02:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcParseRfc3339 ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pUtc , vm : : cptr < char > pszDateTime ) ;
2024-04-06 01:46:33 +02:00
2020-04-09 14:54:41 +02:00
/*
Takes a RFC2822 / RFC3339 / asctime String , and converts it to a CellRtcTick
*/
2024-04-18 17:11:59 +02:00
error_code cellRtcParseDateTime ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pUtc , vm : : cptr < char > pszDateTime )
2016-03-21 20:43:03 +01:00
{
2024-04-20 15:41:42 +02:00
cellRtc . notice ( " cellRtcParseDateTime(pUtc=*0x%x, pszDateTime=%s) " , pUtc , pszDateTime ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pUtc . addr ( ) , page_attr ) ! = CELL_OK | | sys_memory_get_page_attribute ( ppu , pszDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2024-04-06 00:39:11 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-06 01:46:33 +02:00
u32 pos = 0 ;
2024-04-08 12:46:04 +02:00
while ( std : : isblank ( pszDateTime [ pos ] ) )
2024-04-06 01:46:33 +02:00
{
pos + + ;
}
if ( std : : isdigit ( pszDateTime [ pos ] ) & &
std : : isdigit ( pszDateTime [ pos + 1 ] ) & &
std : : isdigit ( pszDateTime [ pos + 2 ] ) & &
std : : isdigit ( pszDateTime [ pos + 3 ] ) )
{
2024-04-18 17:11:59 +02:00
return cellRtcParseRfc3339 ( ppu , pUtc , pszDateTime + pos ) ;
2024-04-06 01:46:33 +02:00
}
2024-04-20 15:41:42 +02:00
// Day of the week: at least the first three letters
if ( rtcParseName ( pszDateTime , pos , WEEKDAY_NAMES ) = = WEEKDAY_NAMES . size ( ) ) // No match
{
return { CELL_RTC_ERROR_BAD_PARSE , " cellRtcParseDateTime(): failed to parse day of the week: string at position %d doesn't match any name " , pos } ;
}
2020-04-09 14:54:41 +02:00
2024-04-20 15:41:42 +02:00
// Optional comma
if ( pszDateTime [ pos ] = = ' , ' )
{
pos + + ;
}
// Skip spaces and tabs
while ( std : : isblank ( pszDateTime [ pos ] ) )
{
pos + + ;
}
// Month: at least the first three letters
const u16 month = rtcParseName ( pszDateTime , pos , MONTH_NAMES ) + 1 ;
2020-04-09 14:54:41 +02:00
2024-04-20 15:41:42 +02:00
if ( month > MONTH_NAMES . size ( ) ) // No match
{
cellRtc . notice ( " cellRtcParseDateTime(): string uses RFC 2822 format " ) ;
2024-04-18 17:11:59 +02:00
return rtcParseRfc2822 ( ppu , pUtc , pszDateTime , pos ) ;
2024-04-20 15:41:42 +02:00
}
2020-04-09 14:54:41 +02:00
2024-04-20 15:41:42 +02:00
// Mandatory space
if ( pszDateTime [ pos ] ! = ' ' )
2020-04-09 14:54:41 +02:00
{
2024-04-20 15:41:42 +02:00
return { CELL_RTC_ERROR_BAD_PARSE , " cellRtcParseDateTime(): no space after month " } ;
}
pos + + ;
// Day: " X", "XX" or "X"
// There may be a second space before day
u16 day = 0 ;
if ( pszDateTime [ pos ] = = ' ' )
{
pos + + ;
// Due to using a signed type instead of unsigned, LLE doesn't check if the char is less than '0'
if ( pszDateTime [ pos ] > ' 9 ' )
2020-04-09 14:54:41 +02:00
{
2024-04-20 15:41:42 +02:00
return { CELL_RTC_ERROR_BAD_PARSE , " cellRtcParseDateTime(): failed to parse day: ASCII value 0x%x at position %d is not a digit " , pszDateTime [ pos ] , pos } ;
2020-04-09 14:54:41 +02:00
}
2024-04-20 15:41:42 +02:00
if ( pszDateTime [ pos ] < ' 0 ' )
2020-04-09 14:54:41 +02:00
{
2024-04-20 15:41:42 +02:00
cellRtc . warning ( " cellRtcParseDateTime(): ASCII value 0x%x at position %d is not a digit " , pszDateTime [ pos ] , pos ) ;
2020-04-09 14:54:41 +02:00
}
2024-04-20 15:41:42 +02:00
2024-04-18 16:45:26 +02:00
day = static_cast < u16 > ( pszDateTime [ pos ] ) - ' 0 ' ; // Needs to be sign extended first to match LLE for values from 0x80 to 0xb0
2024-04-20 15:41:42 +02:00
pos + + ;
2020-04-09 14:54:41 +02:00
}
2024-04-20 15:41:42 +02:00
else if ( std : : isdigit ( pszDateTime [ pos ] ) )
2020-04-09 14:54:41 +02:00
{
2024-04-20 15:41:42 +02:00
day = digit ( pszDateTime [ pos ] ) ;
pos + + ;
if ( std : : isdigit ( pszDateTime [ pos ] ) )
2020-04-09 14:54:41 +02:00
{
2024-04-20 15:41:42 +02:00
day = day * 10 + digit ( pszDateTime [ pos ] ) ;
pos + + ;
2020-04-09 14:54:41 +02:00
}
}
2024-04-20 15:41:42 +02:00
else
{
return { CELL_RTC_ERROR_BAD_PARSE , " cellRtcParseDateTime(): failed to parse day: ASCII value 0x%x at position %d is not a digit or space " , pszDateTime [ pos ] , pos } ;
}
// Hour: " X" or " XX"
const u16 hour = rtcParseComponent ( pszDateTime , pos , ' ' , " hour " ) ;
if ( hour = = umax )
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
// Minute: ":X" or ":XX"
const u16 minute = rtcParseComponent ( pszDateTime , pos , ' : ' , " minute " ) ;
if ( minute = = umax )
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
// Second: ":X" or ":XX"
const u16 second = rtcParseComponent ( pszDateTime , pos , ' : ' , " second " ) ;
if ( second = = umax )
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
// Mandatory space
if ( pszDateTime [ pos ] ! = ' ' )
{
return { CELL_RTC_ERROR_BAD_PARSE , " cellRtcParseDateTime(): no space after second " } ;
}
pos + + ;
// Year: XXXX
if ( ! std : : isdigit ( pszDateTime [ pos ] ) | |
! std : : isdigit ( pszDateTime [ pos + 1 ] ) | |
! std : : isdigit ( pszDateTime [ pos + 2 ] ) | |
! std : : isdigit ( pszDateTime [ pos + 3 ] ) )
{
return { CELL_RTC_ERROR_BAD_PARSE , " cellRtcParseDateTime(): failed to parse year: one of the ASCII values 0x%x, 0x%x, 0x%x, or 0x%x is not a digit " ,
pszDateTime [ pos ] , pszDateTime [ pos + 1 ] , pszDateTime [ pos + 2 ] , pszDateTime [ pos + 3 ] } ;
}
const u16 year = digit ( pszDateTime [ pos ] ) * 1000 + digit ( pszDateTime [ pos + 1 ] ) * 100 + digit ( pszDateTime [ pos + 2 ] ) * 10 + digit ( pszDateTime [ pos + 3 ] ) ;
const vm : : var < CellRtcDateTime > date_time { { year , month , day , hour , minute , second , 0 } } ;
2020-04-09 14:54:41 +02:00
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , date_time , pUtc ) ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-06 00:39:11 +02:00
// Rfc3339: 1995-12-03T13:23:00.00Z
2024-04-18 17:11:59 +02:00
error_code cellRtcParseRfc3339 ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pUtc , vm : : cptr < char > pszDateTime )
2016-03-21 20:43:03 +01:00
{
2024-04-08 12:46:04 +02:00
cellRtc . notice ( " cellRtcParseRfc3339(pUtc=*0x%x, pszDateTime=%s) " , pUtc , pszDateTime ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pUtc . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pszDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcDateTime > date_time ;
2024-04-06 00:39:11 +02:00
// Year: XXXX-12-03T13:23:00.00Z
if ( std : : isdigit ( pszDateTime [ 0 ] ) & & std : : isdigit ( pszDateTime [ 1 ] ) & & std : : isdigit ( pszDateTime [ 2 ] ) & & std : : isdigit ( pszDateTime [ 3 ] ) )
2020-04-09 14:54:41 +02:00
{
2024-04-06 00:39:11 +02:00
date_time - > year = digit ( pszDateTime [ 0 ] ) * 1000 + digit ( pszDateTime [ 1 ] ) * 100 + digit ( pszDateTime [ 2 ] ) * 10 + digit ( pszDateTime [ 3 ] ) ;
2020-04-09 14:54:41 +02:00
}
else
{
date_time - > year = 0xffff ;
}
if ( pszDateTime [ 4 ] ! = ' - ' )
{
return CELL_RTC_ERROR_INVALID_YEAR ;
}
2024-04-06 00:39:11 +02:00
// Month: 1995-XX-03T13:23:00.00Z
if ( std : : isdigit ( pszDateTime [ 5 ] ) & & std : : isdigit ( pszDateTime [ 6 ] ) )
{
date_time - > month = digit ( pszDateTime [ 5 ] ) * 10 + digit ( pszDateTime [ 6 ] ) ;
}
else
2020-04-09 14:54:41 +02:00
{
date_time - > month = 0xffff ;
}
if ( pszDateTime [ 7 ] ! = ' - ' )
{
return CELL_RTC_ERROR_INVALID_MONTH ;
}
2024-04-06 00:39:11 +02:00
// Day: 1995-12-XXT13:23:00.00Z
if ( std : : isdigit ( pszDateTime [ 8 ] ) & & std : : isdigit ( pszDateTime [ 9 ] ) )
{
date_time - > day = digit ( pszDateTime [ 8 ] ) * 10 + digit ( pszDateTime [ 9 ] ) ;
}
else
2020-04-09 14:54:41 +02:00
{
date_time - > day = 0xffff ;
}
if ( pszDateTime [ 10 ] ! = ' T ' & & pszDateTime [ 10 ] ! = ' t ' )
{
return CELL_RTC_ERROR_INVALID_DAY ;
}
2024-04-06 00:39:11 +02:00
// Hour: 1995-12-03TXX:23:00.00Z
if ( std : : isdigit ( pszDateTime [ 11 ] ) & & std : : isdigit ( pszDateTime [ 12 ] ) )
{
date_time - > hour = digit ( pszDateTime [ 11 ] ) * 10 + digit ( pszDateTime [ 12 ] ) ;
}
else
2020-04-09 14:54:41 +02:00
{
date_time - > hour = 0xffff ;
}
2024-04-06 00:39:11 +02:00
if ( pszDateTime [ 13 ] ! = ' : ' )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_HOUR ;
}
2024-04-06 00:39:11 +02:00
// Minute: 1995-12-03T13:XX:00.00Z
if ( std : : isdigit ( pszDateTime [ 14 ] ) & & std : : isdigit ( pszDateTime [ 15 ] ) )
{
date_time - > minute = digit ( pszDateTime [ 14 ] ) * 10 + digit ( pszDateTime [ 15 ] ) ;
}
else
2020-04-09 14:54:41 +02:00
{
date_time - > minute = 0xffff ;
}
2024-04-06 00:39:11 +02:00
if ( pszDateTime [ 16 ] ! = ' : ' )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_MINUTE ;
}
2024-04-06 00:39:11 +02:00
// Second: 1995-12-03T13:23:XX.00Z
if ( std : : isdigit ( pszDateTime [ 17 ] ) & & std : : isdigit ( pszDateTime [ 18 ] ) )
{
date_time - > second = digit ( pszDateTime [ 17 ] ) * 10 + digit ( pszDateTime [ 18 ] ) ;
}
else
2020-04-09 14:54:41 +02:00
{
date_time - > second = 0xffff ;
}
2024-04-06 00:39:11 +02:00
// Microsecond: 1995-12-03T13:23:00.XXZ
date_time - > microsecond = 0 ;
u32 pos = 19 ;
if ( pszDateTime [ pos ] = = ' . ' )
2020-04-09 14:54:41 +02:00
{
2024-04-06 00:39:11 +02:00
u32 mul = 100000 ;
2024-04-07 09:27:00 +02:00
for ( char c = pszDateTime [ + + pos ] ; std : : isdigit ( c ) ; c = pszDateTime [ + + pos ] )
2020-04-09 14:54:41 +02:00
{
2024-04-06 00:39:11 +02:00
date_time - > microsecond + = digit ( c ) * mul ;
mul / = 10 ;
2020-04-09 14:54:41 +02:00
}
}
2024-04-06 00:39:11 +02:00
const char sign = pszDateTime [ pos ] ;
if ( sign ! = ' Z ' & & sign ! = ' z ' & & sign ! = ' + ' & & sign ! = ' - ' )
2020-04-09 14:54:41 +02:00
{
2024-04-06 00:39:11 +02:00
return CELL_RTC_ERROR_BAD_PARSE ;
2020-04-09 14:54:41 +02:00
}
2024-04-06 00:39:11 +02:00
s64 minutes_to_add = 0 ;
// Time offset: 1995-12-03T13:23:00.00+02:30
if ( sign = = ' + ' | | sign = = ' - ' )
2020-04-09 14:54:41 +02:00
{
2024-04-06 00:39:11 +02:00
if ( ! std : : isdigit ( pszDateTime [ pos + 1 ] ) | |
! std : : isdigit ( pszDateTime [ pos + 2 ] ) | |
pszDateTime [ pos + 3 ] ! = ' : ' | |
! std : : isdigit ( pszDateTime [ pos + 4 ] ) | |
! std : : isdigit ( pszDateTime [ pos + 5 ] ) )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_BAD_PARSE ;
}
2024-04-06 00:39:11 +02:00
// Time offset (hours): 1995-12-03T13:23:00.00+XX:30
const s32 hours = digit ( pszDateTime [ pos + 1 ] ) * 10 + digit ( pszDateTime [ pos + 2 ] ) ;
// Time offset (minutes): 1995-12-03T13:23:00.00+02:XX
const s32 minutes = digit ( pszDateTime [ pos + 4 ] ) * 10 + digit ( pszDateTime [ pos + 5 ] ) ;
minutes_to_add = hours * 60 + minutes ;
2024-04-08 12:46:04 +02:00
if ( sign = = ' + ' )
2020-04-09 14:54:41 +02:00
{
2024-04-06 00:39:11 +02:00
minutes_to_add = - minutes_to_add ;
2020-04-09 14:54:41 +02:00
}
}
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , date_time , pUtc ) ;
cellRtcTickAddMinutes ( ppu , pUtc , pUtc , minutes_to_add ) ;
2020-04-09 14:54:41 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetTick ( ppu_thread & ppu , vm : : cptr < CellRtcDateTime > pTime , vm : : ptr < CellRtcTick > pTick )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . trace ( " cellRtcGetTick(pTime=*0x%x, pTick=*0x%x) " , pTime , pTick ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
if ( pTime - > year > = 10000 | | pTime - > year = = 0 )
{
return CELL_RTC_ERROR_INVALID_VALUE ;
}
2024-04-09 23:36:42 +02:00
pTick - > tick = date_time_to_tick ( * pTime ) ;
2020-04-09 14:54:41 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2023-05-15 23:22:13 +02:00
CellRtcDateTime tick_to_date_time ( u64 tick )
2016-03-21 20:43:03 +01:00
{
2023-05-15 23:22:13 +02:00
const u32 microseconds = ( tick % 1000000ULL ) ;
const u16 seconds = ( tick / ( 1000000ULL ) ) % 60 ;
const u16 minutes = ( tick / ( 60ULL * 1000000ULL ) ) % 60 ;
const u16 hours = ( tick / ( 60ULL * 60ULL * 1000000ULL ) ) % 24 ;
2024-04-11 15:16:13 +02:00
u32 days_tmp = static_cast < u32 > ( tick / ( 24ULL * 60ULL * 60ULL * 1000000ULL ) ) ;
2020-04-09 14:54:41 +02:00
2024-04-09 23:36:42 +02:00
const u32 year_400 = days_tmp / DAYS_IN_400_YEARS ;
days_tmp - = year_400 * DAYS_IN_400_YEARS ;
const u32 year_within_400_interval = (
days_tmp
- days_tmp / ( DAYS_IN_4_YEARS - 1 )
+ days_tmp / DAYS_IN_100_YEARS
- days_tmp / ( DAYS_IN_400_YEARS - 1 )
) / 365 ;
2020-04-09 14:54:41 +02:00
2024-04-09 23:36:42 +02:00
days_tmp - = year_within_400_interval * 365 + year_within_400_interval / 4 - year_within_400_interval / 100 + year_within_400_interval / 400 ;
const u16 years = year_400 * 400 + year_within_400_interval + 1 ;
const auto & month_offset = is_leap_year ( years ) ? MONTH_OFFSET_LEAP : MONTH_OFFSET ;
u32 month_approx = days_tmp / 29 ;
if ( month_offset [ month_approx ] > days_tmp )
2020-04-09 14:54:41 +02:00
{
2024-04-09 23:36:42 +02:00
month_approx - - ;
}
2020-04-09 14:54:41 +02:00
2024-04-09 23:36:42 +02:00
const u16 months = month_approx + 1 ;
days_tmp = days_tmp - month_offset [ month_approx ] ;
2020-04-09 14:54:41 +02:00
2023-05-15 23:22:13 +02:00
CellRtcDateTime date_time {
. year = years ,
. month = months ,
. day = : : narrow < u16 > ( days_tmp + 1 ) ,
. hour = hours ,
. minute = minutes ,
. second = seconds ,
. microsecond = microseconds
} ;
return date_time ;
}
2023-11-17 21:33:30 +01:00
u64 date_time_to_tick ( CellRtcDateTime date_time )
{
2024-04-09 23:36:42 +02:00
const u32 days_in_previous_years =
date_time . year * 365
+ ( date_time . year + 3 ) / 4
- ( date_time . year + 99 ) / 100
+ ( date_time . year + 399 ) / 400
- 366 ;
2023-11-17 21:33:30 +01:00
2024-04-11 15:16:13 +02:00
// Not checked on LLE
if ( date_time . month = = 0u )
{
cellRtc . warning ( " date_time_to_tick(): month invalid, clamping to 1 " ) ;
date_time . month = 1 ;
}
else if ( date_time . month > 12u )
{
cellRtc . warning ( " date_time_to_tick(): month invalid, clamping to 12 " ) ;
date_time . month = 12 ;
}
2023-11-17 21:33:30 +01:00
2024-04-09 23:36:42 +02:00
const u16 days_in_previous_months = is_leap_year ( date_time . year ) ? MONTH_OFFSET_LEAP [ date_time . month - 1 ] : MONTH_OFFSET [ date_time . month - 1 ] ;
2023-11-17 21:33:30 +01:00
2024-04-09 23:36:42 +02:00
const u32 days = days_in_previous_years + days_in_previous_months + date_time . day - 1 ;
2023-11-17 21:33:30 +01:00
u64 tick = date_time . microsecond
+ u64 { date_time . second } * 1000000ULL
+ u64 { date_time . minute } * 60ULL * 1000000ULL
+ u64 { date_time . hour } * 60ULL * 60ULL * 1000000ULL
+ days * 24ULL * 60ULL * 60ULL * 1000000ULL ;
return tick ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcSetTick ( ppu_thread & ppu , vm : : ptr < CellRtcDateTime > pTime , vm : : cptr < CellRtcTick > pTick )
2023-05-15 23:22:13 +02:00
{
2024-04-18 16:45:26 +02:00
cellRtc . trace ( " cellRtcSetTick(pTime=*0x%x, pTick=*0x%x) " , pTime , pTick ) ;
2023-05-15 23:22:13 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTime . addr ( ) , page_attr ) ! = CELL_OK )
2023-05-15 23:22:13 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick . addr ( ) , page_attr ) ! = CELL_OK )
2023-05-15 23:22:13 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
* pTime = tick_to_date_time ( pTick - > tick ) ;
2020-04-09 14:54:41 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddTicks ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s64 lAdd )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcTickAddTicks(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld) " , pTick0 , pTick1 , lAdd ) ;
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
pTick0 - > tick = pTick1 - > tick + lAdd ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddMicroseconds ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s64 lAdd )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcTickAddMicroseconds(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld) " , pTick0 , pTick1 , lAdd ) ;
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
pTick0 - > tick = pTick1 - > tick + lAdd ;
2018-08-25 14:39:00 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddSeconds ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s64 lAdd )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcTickAddSeconds(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld) " , pTick0 , pTick1 , lAdd ) ;
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
pTick0 - > tick = pTick1 - > tick + lAdd * cellRtcGetTickResolution ( ) ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddMinutes ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s64 lAdd )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcTickAddMinutes(pTick0=*0x%x, pTick1=*0x%x, lAdd=%lld) " , pTick0 , pTick1 , lAdd ) ;
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
pTick0 - > tick = pTick1 - > tick + lAdd * 60 * cellRtcGetTickResolution ( ) ;
2018-08-25 14:39:00 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddHours ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s32 iAdd )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcTickAddHours(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d) " , pTick0 , pTick1 , iAdd ) ;
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
pTick0 - > tick = pTick1 - > tick + iAdd * 60ULL * 60ULL * cellRtcGetTickResolution ( ) ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddDays ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s32 iAdd )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcTickAddDays(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d) " , pTick0 , pTick1 , iAdd ) ;
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
pTick0 - > tick = pTick1 - > tick + iAdd * 60ULL * 60ULL * 24ULL * cellRtcGetTickResolution ( ) ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddWeeks ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s32 iAdd )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcTickAddWeeks(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d) " , pTick0 , pTick1 , iAdd ) ;
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
pTick0 - > tick = pTick1 - > tick + iAdd * 60ULL * 60ULL * 24ULL * 7ULL * cellRtcGetTickResolution ( ) ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddMonths ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s32 iAdd )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcTickAddMonths(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d) " , pTick0 , pTick1 , iAdd ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcDateTime > date_time ;
2024-04-18 17:11:59 +02:00
cellRtcSetTick ( ppu , date_time , pTick1 ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 16:45:26 +02:00
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 ;
2020-04-09 14:54:41 +02:00
2024-04-27 10:54:41 +02:00
s32 month_days ;
2020-04-11 22:13:56 +02:00
2024-04-18 16:45:26 +02:00
if ( new_year = = 0u | | new_month < 1u | | new_month > 12u )
2020-04-09 14:54:41 +02:00
{
2024-04-27 10:54:41 +02:00
month_days = CELL_RTC_ERROR_INVALID_ARG ; // LLE writes the error to this variable
2020-04-09 14:54:41 +02:00
}
else
{
2024-04-18 16:45:26 +02:00
month_days = is_leap_year ( new_year ) ? DAYS_IN_MONTH_LEAP [ new_month - 1 ] : DAYS_IN_MONTH [ new_month - 1 ] ;
2020-04-09 14:54:41 +02:00
}
2024-04-27 10:54:41 +02:00
if ( month_days < static_cast < s32 > ( date_time - > day ) )
2020-04-09 14:54:41 +02:00
{
2024-04-27 10:54:41 +02:00
date_time - > day = static_cast < u16 > ( month_days ) ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
date_time - > month = new_month ;
date_time - > year = new_year ;
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , date_time , pTick0 ) ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcTickAddYears ( ppu_thread & ppu , vm : : ptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 , s32 iAdd )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcTickAddYears(pTick0=*0x%x, pTick1=*0x%x, iAdd=%d) " , pTick0 , pTick1 , iAdd ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pTick0 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTick1 . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcDateTime > date_time ;
2024-04-18 17:11:59 +02:00
cellRtcSetTick ( ppu , date_time , pTick1 ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 16:45:26 +02:00
const u16 month = date_time - > month ;
const u16 new_year = date_time - > year + iAdd ;
2020-04-09 14:54:41 +02:00
2024-04-27 10:54:41 +02:00
s32 month_days ;
2020-04-11 22:13:56 +02:00
2024-04-18 16:45:26 +02:00
if ( new_year = = 0u | | month < 1u | | month > 12u )
2020-04-09 14:54:41 +02:00
{
2024-04-27 10:54:41 +02:00
month_days = CELL_RTC_ERROR_INVALID_ARG ; // LLE writes the error to this variable
2020-04-09 14:54:41 +02:00
}
else
{
2024-04-18 16:45:26 +02:00
month_days = is_leap_year ( new_year ) ? DAYS_IN_MONTH_LEAP [ month - 1 ] : DAYS_IN_MONTH [ month - 1 ] ;
2020-04-09 14:54:41 +02:00
}
2024-04-27 10:54:41 +02:00
if ( month_days < static_cast < s32 > ( date_time - > day ) )
2020-04-09 14:54:41 +02:00
{
2024-04-27 10:54:41 +02:00
date_time - > day = static_cast < u16 > ( month_days ) ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
date_time - > year = new_year ;
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , date_time , pTick0 ) ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcConvertUtcToLocalTime ( ppu_thread & ppu , vm : : cptr < CellRtcTick > pUtc , vm : : ptr < CellRtcTick > pLocalTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . trace ( " cellRtcConvertUtcToLocalTime(pUtc=*0x%x, pLocalTime=*0x%x) " , pUtc , pLocalTime ) ;
2016-03-21 20:43:03 +01:00
2020-04-09 14:54:41 +02:00
vm : : var < s32 > timezone ;
vm : : var < s32 > summertime ;
error_code ret = sys_time_get_timezone ( timezone , summertime ) ;
if ( - 1 < ret )
{
2024-04-18 17:11:59 +02:00
ret = cellRtcTickAddMinutes ( ppu , pLocalTime , pUtc , * timezone + * summertime ) ;
2020-04-09 14:54:41 +02:00
}
return ret ;
2016-03-21 20:43:03 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcConvertLocalTimeToUtc ( ppu_thread & ppu , vm : : cptr < CellRtcTick > pLocalTime , vm : : ptr < CellRtcTick > pUtc )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcConvertLocalTimeToUtc(pLocalTime=*0x%x, pUtc=*0x%x) " , pLocalTime , pUtc ) ;
2016-03-21 20:43:03 +01:00
2020-04-09 14:54:41 +02:00
vm : : var < s32 > timezone ;
vm : : var < s32 > summertime ;
error_code ret = sys_time_get_timezone ( timezone , summertime ) ;
if ( - 1 < ret )
{
2024-04-18 17:11:59 +02:00
ret = cellRtcTickAddMinutes ( ppu , pUtc , pLocalTime , - ( * timezone + * summertime ) ) ;
2020-04-09 14:54:41 +02:00
}
return ret ;
2016-03-21 20:43:03 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetCurrentSecureTick ( ppu_thread & ppu , vm : : ptr < CellRtcTick > tick )
2017-02-13 03:46:02 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcGetCurrentSecureTick(tick=*0x%x) " , tick ) ;
2021-03-05 20:05:37 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , tick . addr ( ) , page_attr ) ! = CELL_OK )
2022-10-15 15:22:36 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 16:45:26 +02:00
tick - > tick = RTC_SYSTEM_TIME_MIN ;
2022-10-15 15:22:36 +02:00
2024-04-18 16:45:26 +02:00
const vm : : var < u64 > time { 0 } ;
const vm : : var < u64 > status { 0 } ;
2024-04-06 00:39:11 +02:00
2024-04-18 16:45:26 +02:00
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 ;
2024-04-27 10:54:41 +02:00
default : return ret ;
2024-04-18 16:45:26 +02:00
}
}
return ret ;
2017-02-13 03:46:02 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetDosTime ( ppu_thread & ppu , vm : : cptr < CellRtcDateTime > pDateTime , vm : : ptr < u32 > puiDosTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcGetDosTime(pDateTime=*0x%x, puiDosTime=*0x%x) " , pDateTime , puiDosTime ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , puiDosTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
if ( pDateTime - > year < 1980 )
{
2024-04-18 16:45:26 +02:00
if ( puiDosTime ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
* puiDosTime = 0 ;
}
2024-04-18 16:45:26 +02:00
return - 1 ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
if ( pDateTime - > year > = 2108 )
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
if ( puiDosTime ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
* puiDosTime = 0xff9fbf7d ; // kHighDosTime
}
2024-04-18 16:45:26 +02:00
return - 1 ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
if ( puiDosTime ) // Should always evaluate to true, nullptr was already checked above
{
2020-04-09 14:54:41 +02:00
s32 year = ( ( pDateTime - > year - 1980 ) & 0x7F ) < < 9 ;
s32 month = ( ( pDateTime - > month ) & 0xF ) < < 5 ;
s32 hour = ( ( pDateTime - > hour ) & 0x1F ) < < 11 ;
s32 minute = ( ( pDateTime - > minute ) & 0x3F ) < < 5 ;
s32 day = ( pDateTime - > day ) & 0x1F ;
s32 second = ( ( pDateTime - > second ) > > 1 ) & 0x1F ;
s32 ymd = year | month | day ;
s32 hms = hour | minute | second ;
* puiDosTime = ( ymd < < 16 ) | hms ;
}
2024-04-18 16:45:26 +02:00
return CELL_OK ;
2016-03-21 20:43:03 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetSystemTime ( ppu_thread & ppu , vm : : cptr < CellRtcDateTime > pDateTime , vm : : ptr < s64 > pTimeStamp )
2017-02-13 03:46:02 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcGetSystemTime(pDateTime=*0x%x, pTimeStamp=*0x%x) " , pDateTime , pTimeStamp ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pTimeStamp . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , pDateTime , tick ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 16:45:26 +02:00
if ( tick - > tick < RTC_SYSTEM_TIME_MIN )
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
if ( pTimeStamp ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
* pTimeStamp = 0 ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
return CELL_RTC_ERROR_INVALID_VALUE ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
if ( tick - > tick > = RTC_SYSTEM_TIME_MAX + cellRtcGetTickResolution ( ) )
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
if ( pTimeStamp ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
* pTimeStamp = ( RTC_SYSTEM_TIME_MAX - RTC_SYSTEM_TIME_MIN ) / cellRtcGetTickResolution ( ) ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
return CELL_RTC_ERROR_INVALID_VALUE ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
if ( pTimeStamp ) // Should always evaluate to true, nullptr was already checked above
{
* pTimeStamp = ( tick - > tick - RTC_SYSTEM_TIME_MIN ) / cellRtcGetTickResolution ( ) ;
}
return CELL_OK ;
2017-02-13 03:46:02 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetTime_t ( ppu_thread & ppu , vm : : cptr < CellRtcDateTime > pDateTime , vm : : ptr < s64 > piTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcGetTime_t(pDateTime=*0x%x, piTime=*0x%x) " , pDateTime , piTime ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , piTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , pDateTime , tick ) ;
2020-04-09 14:54:41 +02:00
if ( tick - > tick < RTC_MAGIC_OFFSET )
{
2024-04-18 16:45:26 +02:00
if ( piTime ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
* piTime = 0 ;
}
2024-04-18 16:45:26 +02:00
return CELL_RTC_ERROR_INVALID_VALUE ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
if ( piTime ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
* piTime = ( tick - > tick - RTC_MAGIC_OFFSET ) / cellRtcGetTickResolution ( ) ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
return CELL_OK ;
2016-03-21 20:43:03 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcGetWin32FileTime ( ppu_thread & ppu , vm : : cptr < CellRtcDateTime > pDateTime , vm : : ptr < u64 > pulWin32FileTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcGetWin32FileTime(pDateTime=*0x%x, pulWin32FileTime=*0x%x) " , pDateTime , pulWin32FileTime ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 17:11:59 +02:00
if ( sys_memory_get_page_attribute ( ppu , pulWin32FileTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
2024-04-18 17:11:59 +02:00
cellRtcGetTick ( ppu , pDateTime , tick ) ;
2020-04-09 14:54:41 +02:00
if ( tick - > tick < RTC_FILETIME_OFFSET )
{
2024-04-18 16:45:26 +02:00
if ( pulWin32FileTime ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
* pulWin32FileTime = 0 ;
}
2024-04-18 16:45:26 +02:00
return CELL_RTC_ERROR_INVALID_VALUE ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
if ( pulWin32FileTime ) // Should always evaluate to true, nullptr was already checked above
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
* pulWin32FileTime = ( tick - > tick - RTC_FILETIME_OFFSET ) * 10 ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
return CELL_OK ;
2016-03-21 20:43:03 +01:00
}
2020-04-09 14:54:41 +02:00
error_code cellRtcSetCurrentSecureTick ( vm : : ptr < CellRtcTick > pTick )
2017-02-13 03:46:02 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcSetCurrentSecureTick(pTick=*0x%x) " , pTick ) ;
2020-04-09 14:54:41 +02:00
if ( ! pTick )
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 16:45:26 +02:00
if ( pTick - > tick > RTC_SYSTEM_TIME_MAX )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_VALUE ;
}
2024-04-18 16:45:26 +02:00
return sys_ss_secure_rtc ( 0x3003 , ( pTick - > tick - RTC_SYSTEM_TIME_MIN ) / cellRtcGetTickResolution ( ) , 0 , 0 ) ;
2017-02-13 03:46:02 +01:00
}
2020-04-09 14:54:41 +02:00
error_code cellRtcSetCurrentTick ( vm : : cptr < CellRtcTick > pTick )
2017-02-13 03:46:02 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcSetCurrentTick(pTick=*0x%x) " , pTick ) ;
2020-04-09 14:54:41 +02:00
if ( ! pTick )
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
2024-04-18 16:45:26 +02:00
if ( pTick - > tick < RTC_MAGIC_OFFSET )
2020-04-09 14:54:41 +02:00
{
2024-04-18 16:45:26 +02:00
return CELL_RTC_ERROR_INVALID_VALUE ;
2020-04-09 14:54:41 +02:00
}
2024-04-18 16:45:26 +02:00
const u64 unix_time = pTick - > tick - RTC_MAGIC_OFFSET ;
2020-04-09 14:54:41 +02:00
2024-04-18 16:45:26 +02:00
const error_code ret = sys_time_set_current_time ( unix_time / cellRtcGetTickResolution ( ) , unix_time % cellRtcGetTickResolution ( ) * 1000 ) ;
return ret > = CELL_OK ? CELL_OK : ret ;
2017-02-13 03:46:02 +01:00
}
2020-04-09 14:54:41 +02:00
error_code cellRtcSetConf ( s64 unk1 , s64 unk2 , u32 timezone , u32 summertime )
2017-02-13 03:46:02 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcSetConf(unk1=0x%x, unk2=0x%x, timezone=%d, summertime=%d) " , unk1 , unk2 , timezone , summertime ) ;
2020-04-09 14:54:41 +02:00
// Seems the first 2 args are ignored :|
2024-04-18 16:45:26 +02:00
return sys_time_set_timezone ( timezone , summertime ) ;
2017-02-13 03:46:02 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcSetDosTime ( ppu_thread & ppu , vm : : ptr < CellRtcDateTime > pDateTime , u32 uiDosTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcSetDosTime(pDateTime=*0x%x, uiDosTime=0x%x) " , pDateTime , uiDosTime ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
s32 hms = uiDosTime & 0xffff ;
s32 ymd = uiDosTime > > 16 ;
pDateTime - > year = ( ymd > > 9 ) + 1980 ;
pDateTime - > month = ( ymd > > 5 ) & 0xf ;
pDateTime - > day = ymd & 0x1f ;
pDateTime - > hour = ( hms > > 11 ) ;
pDateTime - > minute = ( hms > > 5 ) & 0x3f ;
pDateTime - > second = ( hms < < 1 ) & 0x3e ;
pDateTime - > microsecond = 0 ;
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 16:45:26 +02:00
constexpr u32 cellRtcGetTickResolution ( )
2017-02-13 03:46:02 +01:00
{
2020-04-09 14:54:41 +02:00
// Amount of ticks in a second
return 1000000 ;
2017-02-13 03:46:02 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcSetTime_t ( ppu_thread & ppu , vm : : ptr < CellRtcDateTime > pDateTime , u64 iTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcSetTime_t(pDateTime=*0x%x, iTime=0x%llx) " , pDateTime , iTime ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
tick - > tick = iTime * cellRtcGetTickResolution ( ) + RTC_MAGIC_OFFSET ;
2024-04-18 17:11:59 +02:00
cellRtcSetTick ( ppu , pDateTime , tick ) ;
2020-04-09 14:54:41 +02:00
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 17:11:59 +02:00
error_code cellRtcSetSystemTime ( ppu_thread & ppu , vm : : ptr < CellRtcDateTime > pDateTime , u64 iTime )
2017-02-13 03:46:02 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcSetSystemTime(pDateTime=*0x%x, iTime=0x%llx) " , pDateTime , iTime ) ;
2020-04-09 14:54:41 +02:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
2024-04-18 16:45:26 +02:00
tick - > tick = iTime * cellRtcGetTickResolution ( ) + RTC_SYSTEM_TIME_MIN ;
2020-04-09 14:54:41 +02:00
2024-04-18 17:11:59 +02:00
cellRtcSetTick ( ppu , pDateTime , tick ) ;
2024-04-18 16:45:26 +02:00
return CELL_OK ;
2017-02-13 03:46:02 +01:00
}
2024-04-18 17:11:59 +02:00
error_code cellRtcSetWin32FileTime ( ppu_thread & ppu , vm : : ptr < CellRtcDateTime > pDateTime , u64 ulWin32FileTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcSetWin32FileTime(pDateTime=*0x%x, ulWin32FileTime=0x%llx) " , pDateTime , ulWin32FileTime ) ;
2016-03-21 20:43:03 +01:00
2024-04-18 17:11:59 +02:00
const vm : : var < sys_page_attr_t > page_attr ;
if ( sys_memory_get_page_attribute ( ppu , pDateTime . addr ( ) , page_attr ) ! = CELL_OK )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_POINTER ;
}
vm : : var < CellRtcTick > tick ;
tick - > tick = ulWin32FileTime / 10 + RTC_FILETIME_OFFSET ;
2024-04-18 17:11:59 +02:00
return cellRtcSetTick ( ppu , pDateTime , tick ) ;
2016-03-21 20:43:03 +01:00
}
2020-04-09 14:54:41 +02:00
error_code cellRtcIsLeapYear ( s32 year )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcIsLeapYear(year=%d) " , year ) ;
2016-03-21 20:43:03 +01:00
2022-10-15 15:22:36 +02:00
if ( year < 1 )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_ARG ;
}
return not_an_error ( is_leap_year ( year ) ) ;
2016-03-21 20:43:03 +01:00
}
2020-04-09 14:54:41 +02:00
error_code cellRtcGetDaysInMonth ( s32 year , s32 month )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcGetDaysInMonth(year=%d, month=%d) " , year , month ) ;
2016-03-21 20:43:03 +01:00
2022-10-15 15:22:36 +02:00
if ( ( year < = 0 ) | | ( month < = 0 ) | | ( month > 12 ) )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_ARG ;
}
2024-04-18 16:45:26 +02:00
return not_an_error ( is_leap_year ( year ) ? DAYS_IN_MONTH_LEAP [ month - 1 ] : DAYS_IN_MONTH [ month - 1 ] ) ;
2016-03-21 20:43:03 +01:00
}
2024-04-18 16:45:26 +02:00
s32 cellRtcGetDayOfWeek ( s32 year , s32 month , s32 day )
2016-03-21 20:43:03 +01:00
{
2020-04-09 14:54:41 +02:00
cellRtc . trace ( " cellRtcGetDayOfWeek(year=%d, month=%d, day=%d) " , year , month , day ) ;
2022-10-15 15:22:36 +02:00
if ( month = = 1 | | month = = 2 )
2020-04-09 14:54:41 +02:00
{
2022-10-15 15:22:36 +02:00
year - - ;
month + = 12 ;
2020-04-09 14:54:41 +02:00
}
2016-03-21 20:43:03 +01:00
2024-04-18 16:45:26 +02:00
return ( ( month * 13 + 8 ) / 5 + year + year / 4 - year / 100 + year / 400 + day ) % 7 ;
2016-03-21 20:43:03 +01:00
}
2020-04-09 14:54:41 +02:00
error_code cellRtcCheckValid ( vm : : cptr < CellRtcDateTime > pTime )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
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 ) ;
2020-04-09 14:54:41 +02:00
if ( pTime - > year = = 0 | | pTime - > year > = 10000 )
{
return CELL_RTC_ERROR_INVALID_YEAR ;
}
if ( pTime - > month < 1 | | pTime - > month > 12 )
{
return CELL_RTC_ERROR_INVALID_MONTH ;
}
2024-04-18 16:45:26 +02:00
const auto & days_in_month = is_leap_year ( pTime - > year ) ? DAYS_IN_MONTH_LEAP : DAYS_IN_MONTH ;
2020-04-09 14:54:41 +02:00
2024-04-18 16:45:26 +02:00
if ( pTime - > day = = 0 | | pTime - > day > days_in_month [ pTime - > month - 1 ] )
2020-04-09 14:54:41 +02:00
{
return CELL_RTC_ERROR_INVALID_DAY ;
}
if ( pTime - > hour > = 24 )
{
return CELL_RTC_ERROR_INVALID_HOUR ;
}
if ( pTime - > minute > = 60 )
{
return CELL_RTC_ERROR_INVALID_MINUTE ;
}
if ( pTime - > second > = 60 )
{
return CELL_RTC_ERROR_INVALID_SECOND ;
}
if ( pTime - > microsecond > = cellRtcGetTickResolution ( ) )
{
return CELL_RTC_ERROR_INVALID_MICROSECOND ;
}
2016-03-21 20:43:03 +01:00
return CELL_OK ;
}
2024-04-18 16:45:26 +02:00
s32 cellRtcCompareTick ( vm : : cptr < CellRtcTick > pTick0 , vm : : cptr < CellRtcTick > pTick1 )
2016-03-21 20:43:03 +01:00
{
2024-04-18 16:45:26 +02:00
cellRtc . notice ( " cellRtcCompareTick(pTick0=*0x%x, pTick1=*0x%x) " , pTick0 , pTick1 ) ;
ensure ( ! ! pTick0 & & ! ! pTick1 ) ; // Not checked on LLE
2016-03-21 20:43:03 +01:00
2020-04-09 14:54:41 +02:00
s32 ret = - 1 ;
if ( pTick1 - > tick < = pTick0 - > tick )
{
ret = pTick1 - > tick < pTick0 - > tick ;
}
2024-04-18 16:45:26 +02:00
return ret ;
2016-03-21 20:43:03 +01:00
}
2020-04-09 14:54:41 +02:00
DECLARE ( ppu_module_manager : : cellRtc )
( " cellRtc " , [ ] ( ) {
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellRtc , cellRtcGetCurrentTick ) ;
REG_FUNC ( cellRtc , cellRtcGetCurrentClock ) ;
REG_FUNC ( cellRtc , cellRtcGetCurrentClockLocalTime ) ;
REG_FUNC ( cellRtc , cellRtcFormatRfc2822 ) ;
REG_FUNC ( cellRtc , cellRtcFormatRfc2822LocalTime ) ;
REG_FUNC ( cellRtc , cellRtcFormatRfc3339 ) ;
REG_FUNC ( cellRtc , cellRtcFormatRfc3339LocalTime ) ;
REG_FUNC ( cellRtc , cellRtcParseDateTime ) ;
REG_FUNC ( cellRtc , cellRtcParseRfc3339 ) ;
REG_FUNC ( cellRtc , cellRtcGetTick ) ;
REG_FUNC ( cellRtc , cellRtcSetTick ) ;
2017-02-13 03:46:02 +01:00
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellRtc , cellRtcTickAddTicks ) ;
REG_FUNC ( cellRtc , cellRtcTickAddMicroseconds ) ;
REG_FUNC ( cellRtc , cellRtcTickAddSeconds ) ;
REG_FUNC ( cellRtc , cellRtcTickAddMinutes ) ;
REG_FUNC ( cellRtc , cellRtcTickAddHours ) ;
REG_FUNC ( cellRtc , cellRtcTickAddDays ) ;
REG_FUNC ( cellRtc , cellRtcTickAddWeeks ) ;
REG_FUNC ( cellRtc , cellRtcTickAddMonths ) ;
REG_FUNC ( cellRtc , cellRtcTickAddYears ) ;
2017-02-13 03:46:02 +01:00
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellRtc , cellRtcConvertUtcToLocalTime ) ;
REG_FUNC ( cellRtc , cellRtcConvertLocalTimeToUtc ) ;
2017-02-13 03:46:02 +01:00
REG_FUNC ( cellRtc , cellRtcGetCurrentSecureTick ) ;
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellRtc , cellRtcGetDosTime ) ;
2017-02-13 03:46:02 +01:00
REG_FUNC ( cellRtc , cellRtcGetTickResolution ) ;
REG_FUNC ( cellRtc , cellRtcGetSystemTime ) ;
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellRtc , cellRtcGetTime_t ) ;
REG_FUNC ( cellRtc , cellRtcGetWin32FileTime ) ;
2017-02-13 03:46:02 +01:00
REG_FUNC ( cellRtc , cellRtcSetConf ) ;
REG_FUNC ( cellRtc , cellRtcSetCurrentSecureTick ) ;
REG_FUNC ( cellRtc , cellRtcSetCurrentTick ) ;
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellRtc , cellRtcSetDosTime ) ;
REG_FUNC ( cellRtc , cellRtcSetTime_t ) ;
2017-02-13 03:46:02 +01:00
REG_FUNC ( cellRtc , cellRtcSetSystemTime ) ;
2016-03-21 20:43:03 +01:00
REG_FUNC ( cellRtc , cellRtcSetWin32FileTime ) ;
REG_FUNC ( cellRtc , cellRtcIsLeapYear ) ;
REG_FUNC ( cellRtc , cellRtcGetDaysInMonth ) ;
REG_FUNC ( cellRtc , cellRtcGetDayOfWeek ) ;
REG_FUNC ( cellRtc , cellRtcCheckValid ) ;
REG_FUNC ( cellRtc , cellRtcCompareTick ) ;
} ) ;