From a049c6fd6b097bb26c219adc2459d269d08d33ae Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 26 Apr 2021 21:12:06 +0300 Subject: [PATCH] Implement sys_time_get_timezone syscall Try to get system timezone automatically. Attempt to address #10195. --- rpcs3/Emu/Cell/lv2/sys_time.cpp | 65 ++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_time.cpp b/rpcs3/Emu/Cell/lv2/sys_time.cpp index 4e60536912..450ed78e62 100644 --- a/rpcs3/Emu/Cell/lv2/sys_time.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_time.cpp @@ -108,6 +108,8 @@ static int clock_gettime(int clk_id, struct timespec* tp) #ifndef _WIN32 +#include + static struct timespec start_time = []() { struct timespec ts; @@ -118,6 +120,8 @@ static struct timespec start_time = []() std::terminate(); } + tzset(); + return ts; }(); @@ -179,11 +183,68 @@ u64 get_guest_system_time() // Functions error_code sys_time_get_timezone(vm::ptr timezone, vm::ptr summertime) { - sys_time.warning("sys_time_get_timezone(timezone=*0x%x, summertime=*0x%x)", timezone, summertime); + sys_time.notice("sys_time_get_timezone(timezone=*0x%x, summertime=*0x%x)", timezone, summertime); - *timezone = 180; +#ifdef _WIN32 + TIME_ZONE_INFORMATION tz{}; + switch (GetTimeZoneInformation(&tz)) + { + case TIME_ZONE_ID_UNKNOWN: + { + *timezone = -tz.Bias; + *summertime = 0; + break; + } + case TIME_ZONE_ID_STANDARD: + { + *timezone = -tz.Bias; + *summertime = -tz.StandardBias; + + if (tz.StandardBias) + { + sys_time.error("Unexpected timezone bias (base=%d, std=%d, daylight=%d)", tz.Bias, tz.StandardBias, tz.DaylightBias); + } + break; + } + case TIME_ZONE_ID_DAYLIGHT: + { + *timezone = -tz.Bias; + *summertime = -tz.DaylightBias; + break; + } + default: + { + ensure(0); + } + } +#elif __linux__ + tzset(); + *timezone = ::narrow(-::timezone / 60); *summertime = 0; + if (::daylight) + { + struct tm test{}; + ensure(&test == localtime_r(&start_time.tv_sec, &test)); + + // Check bounds [0,1] + if (test.tm_isdst & -2) + { + sys_time.error("No information for timezone DST bias (timezone=%.2fh, tm_gmtoff=%d)", -::timezone / 3600.0, test.tm_gmtoff); + } + else + { + *summertime = ::narrow(test.tm_isdst ? (test.tm_gmtoff + ::timezone) / 60 : 0); + } + } +#else + struct timeval _tv{}; + struct timezone tz{}; + ensure(gettimeofday(&_tv, &tz) == 0); + *timezone = -tz.tz_minuteswest; + *summertime = tz.tz_dsttime ? 60 : 0; // TODO +#endif + return CELL_OK; }