diff --git a/kernel/ps4_libkernel.pas b/kernel/ps4_libkernel.pas index 720eec9..c87808c 100644 --- a/kernel/ps4_libkernel.pas +++ b/kernel/ps4_libkernel.pas @@ -28,6 +28,9 @@ uses Classes, SysUtils; +function ps4___error:Pointer; SysV_ABI_CDecl; +function ps4_sceKernelError(i:Integer):Integer; SysV_ABI_CDecl; + function ps4_sceKernelIsNeoMode:Integer; SysV_ABI_CDecl; function ps4_sceKernelGetCompiledSdkVersion(sdkVersion:PDWORD):Integer; SysV_ABI_CDecl; @@ -1010,6 +1013,11 @@ begin lib^.set_proc($B26223EDEAB3644F,@ps4_clock_getres); lib^.set_proc($94B313F6F240724D,@ps4_clock_gettime); lib^.set_proc($7A37A471A35036AD,@ps4_sceKernelGettimeofday); + + lib^.set_proc($77B9D48F52CE7435,@ps4_clock_settime); + lib^.set_proc($55D5C80C06C9DED4,@ps4_settimeofday); + lib^.set_proc($0A108E0A13D4FD83,@ps4_sceKernelSettimeofday); + lib^.set_proc($D63DD2DE7FED4D6E,@ps4_sceKernelGetTscFrequency); lib^.set_proc($FF62115023BFFCF3,@ps4_sceKernelReadTsc); lib^.set_proc($4018BB1C22B4DE1C,@ps4_sceKernelClockGettime); diff --git a/kernel/ps4_time.pas b/kernel/ps4_time.pas index 9096ef6..5d45482 100644 --- a/kernel/ps4_time.pas +++ b/kernel/ps4_time.pas @@ -37,6 +37,11 @@ function ps4_clock_getres(clock_id:Integer;tp:Ptimespec):Integer; SysV_ABI_CDecl function ps4_clock_gettime(clock_id:Integer;tp:Ptimespec):Integer; SysV_ABI_CDecl; function ps4_sceKernelGettimeofday(tv:Ptimeval):Integer; SysV_ABI_CDecl; + +function ps4_clock_settime(clock_id:Integer;tp:Ptimespec):Integer; SysV_ABI_CDecl; +function ps4_settimeofday(tv:Ptimeval;tz:Ptimezone):Integer; SysV_ABI_CDecl; +function ps4_sceKernelSettimeofday(tv:Ptimeval;tz:Ptimezone):Integer; SysV_ABI_CDecl; + function ps4_sceKernelGetTscFrequency():QWORD; SysV_ABI_CDecl; function ps4_sceKernelReadTsc():QWORD; SysV_ABI_CDecl; function ps4_sceKernelClockGettime(clockId:Integer;tp:Ptimespec):Integer; SysV_ABI_CDecl; @@ -142,6 +147,21 @@ begin end; end; +function ps4_clock_settime(clock_id:Integer;tp:Ptimespec):Integer; SysV_ABI_CDecl; +begin + Result:=_set_errno(EPERM); +end; + +function ps4_settimeofday(tv:Ptimeval;tz:Ptimezone):Integer; SysV_ABI_CDecl; +begin + Result:=_set_errno(EPERM); +end; + +function ps4_sceKernelSettimeofday(tv:Ptimeval;tz:Ptimezone):Integer; SysV_ABI_CDecl; +begin + Result:=_set_errno(px2sce(EPERM)); +end; + function ps4_clock_getres(clock_id:Integer;tp:Ptimespec):Integer; SysV_ABI_CDecl; var pc,pf:QWORD; @@ -149,7 +169,8 @@ var TimeAdjustmentDisabled:BOOL; begin if (tp=nil) then Exit(_set_errno(EINVAL)); - Result:=0; + + Result:=_set_errno(0); case clock_id of CLOCK_SECOND: @@ -207,16 +228,13 @@ begin end; -//var -// old_tp:timespec; - function ps4_clock_gettime(clock_id:Integer;tp:Ptimespec):Integer; SysV_ABI_CDecl; var pc,pf:QWORD; begin - if (tp=nil) then Exit(_set_errno(EINVAL)); - Result:=0; + + Result:=_set_errno(0); case clock_id of CLOCK_SECOND: diff --git a/src/ps4_libscertc.pas b/src/ps4_libscertc.pas index ff1f0ce..faa947a 100644 --- a/src/ps4_libscertc.pas +++ b/src/ps4_libscertc.pas @@ -5,8 +5,10 @@ unit ps4_libSceRtc; interface uses + sys_types, ps4_program, ps4_libkernel, + ps4_time, Classes, SysUtils; @@ -51,6 +53,559 @@ begin Result:=0; end; +// + +function _set_tz(tz_minuteswest,tz_dsttime:Integer):Integer; +var + tz:timezone; +begin + tz.tz_minuteswest:=tz_minuteswest; + tz.tz_dsttime :=tz_dsttime; + Result:=ps4_sceKernelSettimeofday(nil,@tz); +end; + +function _sceRtcTickSubMicroseconds(pTick0,pTick1:PQWORD;lSub:Int64):Integer; +var + t1:QWORD; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + t1:=pTick1^; + + if (lSub<0) then + begin + if (t1 < QWORD(-lSub)) then Exit(-$7f4afffd); + end else + begin + if ((not t1) < QWORD(lSub)) then Exit(-$7f4afffd); + end; + + t1:=t1+lSub; + pTick0^:=t1; + Result:=0; +end; + +function _sceRtcTickAddMinutes(pTick0,pTick1:PQWORD;lAdd:Int64):Integer; +var + ladd_mul:QWORD; + t1:QWORD; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + ladd_mul:=lAdd*60000000; + + t1:=pTick1^; + + if (lAdd < 0) then + begin + if (t1 < QWORD(-ladd_mul)) then Exit(-$7f4afffd); + end else + begin + if ((not t1) < QWORD(ladd_mul)) then Exit(-$7f4afffd); + end; + + pTick0^:=t1+ladd_mul; + Result:=0; +end; + + +function leap_year(year:Word):Boolean; inline; +begin + if (year=(((year shr 4) div $19)*400)) then + begin + Result:=True; + end else + if (year=(((year shr 2) div $19)*100)) then + begin + Result:=False; + end else + begin + Result:=(year and 3)=0; + end; +end; + +// + +function ps4_sceRtcTickAddTicks(pTick0,pTick1:PQWORD;lAdd:Int64):Integer; SysV_ABI_CDecl; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + pTick0^:=lAdd+pTick1^; + + Result:=0; +end; + +function ps4_sceRtcTickAddMicroseconds(pTick0,pTick1:PQWORD;lAdd:Int64):Integer; SysV_ABI_CDecl; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + pTick0^:=lAdd+pTick1^; + + Result:=0; +end; + +function ps4_sceRtcTickAddSeconds(pTick0,pTick1:PQWORD;lAdd:Int64):Integer; SysV_ABI_CDecl; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + pTick0^:=(lAdd*1000000)+pTick1^; + + Result:=0; +end; + +function ps4_sceRtcTickAddMinutes(pTick0,pTick1:PQWORD;lAdd:Int64):Integer; SysV_ABI_CDecl; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + pTick0^:=(lAdd*60000000)+pTick1^; + + Result:=0; +end; + +function ps4_sceRtcTickAddHours(pTick0,pTick1:PQWORD;lAdd:Integer):Integer; SysV_ABI_CDecl; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + pTick0^:=(Int64(lAdd)*3600000000)+pTick1^; + + Result:=0; +end; + +function ps4_sceRtcTickAddDays(pTick0,pTick1:PQWORD;lAdd:Integer):Integer; SysV_ABI_CDecl; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + pTick0^:=(Int64(lAdd)*86400000000)+pTick1^; + + Result:=0; +end; + + +function ps4_sceRtcTickAddWeeks(pTick0,pTick1:PQWORD;lAdd:Integer):Integer; SysV_ABI_CDecl; +begin + if (pTick0=nil) or (pTick1=nil) then Exit(-$7f4afffe); + + pTick0^:=(Int64(lAdd)*$8cd0e3a000)+pTick1^; + + Result:=0; +end; + +//TODO sceRtcTickAddMonths +//TODO sceRtcTickAddYears + +// + +function ps4_sceRtcSetConf(param_1,param_2:QWORD;tz_minuteswest,tz_dsttime:Integer):Integer; SysV_ABI_CDecl; +begin + Result:=_set_tz(tz_minuteswest,tz_dsttime); +end; + +function ps4_sceRtcSetCurrentTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + tick:QWORD; + time:timeval; +begin + if (pTick=nil) then Exit(-$7f4afffe); + if (pTick^<=$dcbffeff2bbfff) then Exit(-$7f4afffd); + + tick:=pTick^+$ff23400100d44000; + + time.tv_sec :=tick div 1000000; + time.tv_usec:=tick mod 1000000; + Result:=ps4_sceKernelSettimeofday(@time,nil); +end; + +function ps4_sceRtcGetCurrentTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + time:timespec; +begin + if (pTick=nil) then Exit(-$7f4afffe); + + Result:=ps4_sceKernelClockGettime(0,@time); + + if (Result>=0) then + begin + pTick^:=(time.tv_nsec div 1000) + (time.tv_sec*1000000) + $dcbffeff2bc000; + end +end; + +function ps4_sceRtcSetTick(pTime:pSceRtcDateTime;pTick:PQWORD):Integer; SysV_ABI_CDecl; +label + _skip,_next1,_next2; +var + iVar1:Integer; + uVar2:DWORD; + year:DWORD; + days:DWORD; + ms1:QWORD; + iVar3:Integer; + sec:QWORD; + min:Word; + ms2:QWORD; + leap:Boolean; +begin + if (pTime=nil) or (pTick=nil) then Exit(-$7f4afffe); + + sec := pTick^ div 86400000000; + ms1 := pTick^ mod 86400000000; + ms2 := ms1 div 1000000; + pTime^.microsecond := Integer(ms1) + (Integer(ms2) * -1000000); + min := Word(ms2 div $3c); + pTime^.second := Word(ms1 div 1000000) + (min * -$3c); + year := 1; + pTime^.minute := min + Word((ms2 div $3c) div $3c) * -$3c; + pTime^.hour := Word(ms2 div $e10) - + (Word((ms2 div $e10) div $18) * 8 + + (Word((ms2 div $e10) * $aaaaaaab shr $20) and $fff0)); + if (DWORD(sec) > $23ab0) then + begin + iVar1 := Integer(sec div $23ab1); + year := iVar1 * 400 or 1; + sec := QWORD(iVar1 * -$23ab1 + DWORD(sec)); + end; + uVar2 := DWORD(sec); + if (uVar2 > $8eab) then + begin + iVar1 := Integer((sec shr 2) div $23ab); + iVar3 := iVar1 * 100; + uVar2 := iVar1 * -$8eac + uVar2; + if (uVar2 = 0) then + begin + year := iVar3 + -1 + year; + uVar2 := $16d; + goto _skip; + end; + year := iVar3 + year; + end; + if ($5b4 < uVar2) then + begin + year := year + (uVar2 div $5b5) * 4; + uVar2 := uVar2 mod $5b5; + end; + +_skip: + + repeat + days := year mod 400; + if (((Integer(year) < 1) or (days = 0)) or (((year <> (year div 100) * 100) and ((year and 3) = 0)))) then + begin + iVar1 := -$16e; + if (uVar2 < $16e) then + begin + pTime^.year := Word(year); + if (Integer(year) > 0) then + begin + leap:=True; + if (days <> 0) then + begin +_next1: + leap:=leap_year(Word(year)); + end; + end; +_next2: + year := 0; + repeat + days := uVar2; + year := year + 1; + uVar2 := days - MonthDays[leap][ms1]; + until not (MonthDays[leap][ms1] <= days); + pTime^.month := Word(year); + pTime^.day := Word(days) + 1; + Exit(0); + end; + end else + begin + iVar1 := -$16d; + if (uVar2 < $16d) then + begin + pTime^.year := Word(year); + if (days <> 0) then goto _next1; + leap := True; + goto _next2; + end; + end; + uVar2 := uVar2 + iVar1; + year := year + 1; + until false; + +end; + +function ps4_sceRtcGetCurrentClock(pTime:pSceRtcDateTime;iTimeZone:Integer):Integer; SysV_ABI_CDecl; +var + tick:QWORD; + time:timespec; +begin + if (pTime=nil) then Exit(-$7f4afffe); + + Result:=ps4_sceKernelClockGettime(0,@time); + + if (Result>=0) then + begin + tick:=(time.tv_nsec div 1000) + (time.tv_sec * 1000000) + $dcbffeff2bc000; + ps4_sceRtcTickAddMinutes(@tick,@tick,iTimeZone); + ps4_sceRtcSetTick(pTime,@tick); + end; +end; + +function ps4_sceRtcGetCurrentClockLocalTime(pTime:pSceRtcDateTime):Integer; SysV_ABI_CDecl; +var + local_time:time_t; + _tick,tick:QWORD; + time:timespec; + tsec:timesec; +begin + if (pTime=nil) then Exit(-$7f4afffe); + + Result:=ps4_sceKernelClockGettime(0,@time); + + if (Result>=0) then + begin + _tick:= (time.tv_nsec div 1000) + (time.tv_sec * 1000000); + tick := _tick + $dcbffeff2bc000; + + Result:=ps4_sceKernelConvertUtcToLocaltime(_tick div 1000000,@local_time,@tsec,nil); + if (Result>=0) then + begin + ps4_sceRtcTickAddMinutes(@tick,@tick,(tsec.tz_dstsec + tsec.tz_secwest) div $3c); + ps4_sceRtcSetTick(pTime,@tick); + end; + end; +end; + +function ps4_sceRtcConvertUtcToLocalTime(pUtc,pLocalTime:PQWORD):Integer; SysV_ABI_CDecl; +var + tsec:timesec; + local_time:time_t; +begin + if (pUtc=nil) then Exit(-$7f4afffe); + + Result:=ps4_sceKernelConvertUtcToLocaltime((pUtc^ + $ff23400100d44000) div 1000000,@local_time,@tsec,nil); + + if (Result>=0) then + begin + Result:=_sceRtcTickSubMicroseconds(pLocalTime,pUtc,((tsec.tz_dstsec + tsec.tz_secwest) div $3c) * 60000000); + end; +end; + +function ps4_sceRtcConvertLocalTimeToUtc(pLocalTime,pUtc:PQWORD):Integer; SysV_ABI_CDecl; +var + tsec:timesec; + utc_time:time_t; +begin + if (pLocalTime=nil) then Exit(-$7f4afffe); + + Result:=ps4_sceKernelConvertLocaltimeToUtc((pLocalTime^ + $ff23400100d44000) div 1000000,$ffffffff,@utc_time,@tsec,nil); + + if (Result>=0) then + begin + Result:=ps4_sceRtcTickAddMinutes(pUtc,pLocalTime,-((tsec.tz_dstsec + tsec.tz_secwest) div $3c)); + end; +end; + + +function ps4_sceRtcGetCurrentNetworkTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + perror:Pinteger; + time:timespec; +begin + if (pTick=nil) then Exit(-$7f4afffe); + + Result:=ps4_clock_gettime($10,@time); + if (Result=0) then + begin + pTick^:=(time.tv_nsec div 1000) + (time.tv_sec * 1000000) + $dcbffeff2bc000; + end else + begin + perror:=ps4___error; + Result:=-$7f4affff; + if (perror^<>5) then + begin + Result:=ps4_sceKernelError(perror^); + end; + end; +end; + +function ps4_sceRtcGetCurrentRawNetworkTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + perror:Pinteger; + time:timespec; +begin + if (pTick=nil) then Exit(-$7f4afffe); + + Result:=ps4_clock_gettime($13,@time); + if (Result=0) then + begin + pTick^:=(time.tv_nsec div 1000) + (time.tv_sec * 1000000) + $dcbffeff2bc000; + end else + begin + perror:=ps4___error; + Result:=-$7f4affff; + if (perror^<>5) then + begin + Result:=ps4_sceKernelError(perror^); + end; + end; +end; + +function ps4_sceRtcGetCurrentDebugNetworkTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + perror:Pinteger; + time:timespec; +begin + if (pTick=nil) then Exit(-$7f4afffe); + + Result:=ps4_clock_gettime($11,@time); + if (Result<>0) then + begin + perror:=ps4___error; + Result:=-$7f4affff; + + if (perror^<>5) then + begin + Result:=ps4_sceKernelError(perror^); + if (Result<>-$7f4affff) then Exit; + end; + Result:=ps4_clock_gettime($10,@time); + + Result:=-$7f4affff; + if (perror^<>5) then + begin + Result:=ps4_sceKernelError(perror^); + end; + + Exit; + end; + + pTick^:=(time.tv_nsec div 1000) + (time.tv_sec * 1000000) + $dcbffeff2bc000; + Result:=0; +end; + +function ps4_sceRtcGetCurrentAdNetworkTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + perror:Pinteger; + time:timespec; +begin + if (pTick=nil) then Exit(-$7f4afffe); + + Result:=ps4_clock_gettime($12,@time); + if (Result<>0) then + begin + perror:=ps4___error; + Result:=-$7f4affff; + + if (perror^<>5) then + begin + Result:=ps4_sceKernelError(perror^); + if (Result<>-$7f4affff) then Exit; + end; + Result:=ps4_clock_gettime($10,@time); + + Result:=-$7f4affff; + if (perror^<>5) then + begin + Result:=ps4_sceKernelError(perror^); + end; + + Exit; + end; + + pTick^:=(time.tv_nsec div 1000) + (time.tv_sec * 1000000) + $dcbffeff2bc000; + Result:=0; +end; + +function ps4_sceRtcSetCurrentNetworkTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + perror:Pinteger; + tick:QWORD; + ptime:ptimespec; + time:timespec; +begin + if (pTick=nil) then + begin + ptime:=nil; + end else + begin + if (pTick^<$dcbffeff2bc000) then Exit(-$7f4afffd); + ptime:=@time; + tick:=pTick^+$ff23400100d44000; + time.tv_sec :=(tick div 1000000); + time.tv_nsec:=(tick mod 1000000)*1000; + end; + + Result:=ps4_clock_settime($10,ptime); + if (Result<>0) then + begin + perror:=ps4___error; + Result:=ps4_sceKernelError(perror^); + end; +end; + +function ps4_sceRtcSetCurrentDebugNetworkTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + perror:Pinteger; + tick:QWORD; + ptime:ptimespec; + time:timespec; +begin + if (pTick=nil) then + begin + ptime:=nil; + end else + begin + if (pTick^<$dcbffeff2bc000) then Exit(-$7f4afffd); + ptime:=@time; + tick:=pTick^+$ff23400100d44000; + time.tv_sec :=(tick div 1000000); + time.tv_nsec:=(tick mod 1000000)*1000; + end; + + Result:=ps4_clock_settime($11,ptime); + if (Result<>0) then + begin + perror:=ps4___error; + Result:=ps4_sceKernelError(perror^); + end; +end; + +function ps4_sceRtcSetCurrentAdNetworkTick(pTick:PQWORD):Integer; SysV_ABI_CDecl; +var + perror:Pinteger; + tick:QWORD; + ptime:ptimespec; + time:timespec; +begin + if (pTick=nil) then + begin + ptime:=nil; + end else + begin + if (pTick^<$dcbffeff2bc000) then Exit(-$7f4afffd); + ptime:=@time; + tick:=pTick^+$ff23400100d44000; + time.tv_sec :=(tick div 1000000); + time.tv_nsec:=(tick mod 1000000)*1000; + end; + + Result:=ps4_clock_settime($12,ptime); + if (Result<>0) then + begin + perror:=ps4___error; + Result:=ps4_sceKernelError(perror^); + end; +end; + +function ps4_sceRtcGetTickResolution:Integer; SysV_ABI_CDecl; +begin + Result:=1000000; +end; + +//TODO sceRtcParseDateTime +//TODO sceRtcParseRFC3339 +//TODO sceRtcFormatRFC2822LocalTime +//TODO sceRtcFormatRFC2822 +//TODO sceRtcFormatRFC3339LocalTime +//TODO sceRtcFormatRFC3339 + function ps4_sceRtcIsLeapYear(year:Integer):Integer; SysV_ABI_CDecl; begin if (year<1) then @@ -68,21 +623,83 @@ begin Result:=1; end; -function leap_year(year:Word):Boolean; inline; +function ps4_sceRtcGetDaysInMonth(year,month:Integer):Integer; SysV_ABI_CDecl; +var + leap:Boolean; begin - if (year=(((year shr 4) div $19)*400)) then - begin - Result:=True; - end else - if (year=(((year shr 2) div $19)*100)) then - begin - Result:=False; - end else - begin - Result:=(year and 3)=0; - end; + if (year<=0) then Exit(-$7f4afff8); + if (month>12) then Exit(-$7f4afff7); + + leap:=leap_year(year); + Result:=MonthDays[leap][month-1]; end; +function ps4_sceRtcGetDayOfWeek(year,month,day:Integer):Integer; SysV_ABI_CDecl; +var + month_m1:DWORD; + lVar2:QWORD; + lVar3:QWORD; + lVar4:QWORD; + days:Byte; + leap:Boolean; +begin + + if (SDK_VERSION < $3000000) then + begin + if (year<1) then Exit(-$7f4afff8); + if (month>12) then Exit(-$7f4afff7); + end else + begin + if (month>12) then Exit(-$7f4afff7); + if (year<1) then Exit(-$7f4afff8); + if (year>9999) then Exit(-$7f4afff8); + end; + + month_m1:=month-1; + + leap:=leap_year(year); + days:=MonthDays[leap][month_m1]; + + if ((day <= 0) or (day > days)) then Exit(-$7f4afff6); + + if (month_m1<2) then + begin + month:=month+$c; + end; + + + lVar3 := (year - Integer(month_m1 < 2)); + + // +end; + +{ +ecx: = rsi + 0xc; //month+$c + +r9_7 := int64(edi); + +rdi_6 := (r9 * 0x5c28f5c28f5c28f5) - r9; + +rdx_5 := (r9 * 0xa3d70a3d70a3d70b) + r9; + +rax_4 := int64((esi * 0xd) + 8) * 0x66666667; + +rcx_3 := int64(r8d) + r9 + + ( ( (( r9 >> 0x3f ) >> 0x3e) + r9) >> 2) + + ( (rdi_6 >> 6) + (rdi_6 >> 0x3f) ) + + (rdx_5 >> 8) + + (rdx_5 >> 0x3f) + + int64(Int32( int64(Int32(rax_4 >> 0x21)) + + int64(Int32( rax_4 >> 0x3f )) )); + +rdx_2 := rcx_3 * (0x4924924924924925); + +rdx_1 := rdx_2 >> 1; + +ret := Int32(rcx_3) - (Int32(rdx_1*8) - ( Int32(rdx_1) + Int32( rdx_2 >> 0x3f ))); +} + + function ps4_sceRtcCheckValid(pTime:pSceRtcDateTime):Integer; SysV_ABI_CDecl; var year:WORD; @@ -135,6 +752,7 @@ begin end; initialization + ps4_sceRtcGetDayOfWeek(2022,6,1); //ps4_app.RegistredPreLoad('libSceRtc.prx',@Load_libSceRtc); end.