mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-30 07:29:02 -05:00 
			
		
		
		
	Merge pull request #1665 from ogniK5377/GetClockSnapshot
Implement GetClockSnapshot, ToPosixTime & ToPosixTimeWithMyRule
This commit is contained in:
		| @@ -21,7 +21,7 @@ Time::Time(std::shared_ptr<Module> time, const char* name) | ||||
|         {102, nullptr, "GetStandardUserSystemClockInitialYear"}, | ||||
|         {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"}, | ||||
|         {300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"}, | ||||
|         {400, nullptr, "GetClockSnapshot"}, | ||||
|         {400, &Time::GetClockSnapshot, "GetClockSnapshot"}, | ||||
|         {401, nullptr, "GetClockSnapshotFromSystemClockContext"}, | ||||
|         {500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"}, | ||||
|         {501, nullptr, "CalculateSpanBetween"}, | ||||
|   | ||||
| @@ -15,6 +15,44 @@ | ||||
|  | ||||
| namespace Service::Time { | ||||
|  | ||||
| static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, | ||||
|                             CalendarAdditionalInfo& additional_info, | ||||
|                             [[maybe_unused]] const TimeZoneRule& /*rule*/) { | ||||
|     const std::time_t time(posix_time); | ||||
|     const std::tm* tm = std::localtime(&time); | ||||
|     if (tm == nullptr) { | ||||
|         calendar_time = {}; | ||||
|         additional_info = {}; | ||||
|         return; | ||||
|     } | ||||
|     calendar_time.year = tm->tm_year + 1900; | ||||
|     calendar_time.month = tm->tm_mon + 1; | ||||
|     calendar_time.day = tm->tm_mday; | ||||
|     calendar_time.hour = tm->tm_hour; | ||||
|     calendar_time.minute = tm->tm_min; | ||||
|     calendar_time.second = tm->tm_sec; | ||||
|  | ||||
|     additional_info.day_of_week = tm->tm_wday; | ||||
|     additional_info.day_of_year = tm->tm_yday; | ||||
|     std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC")); | ||||
|     additional_info.utc_offset = 0; | ||||
| } | ||||
|  | ||||
| static u64 CalendarToPosix(const CalendarTime& calendar_time, | ||||
|                            [[maybe_unused]] const TimeZoneRule& /*rule*/) { | ||||
|     std::tm time{}; | ||||
|     time.tm_year = calendar_time.year - 1900; | ||||
|     time.tm_mon = calendar_time.month - 1; | ||||
|     time.tm_mday = calendar_time.day; | ||||
|  | ||||
|     time.tm_hour = calendar_time.hour; | ||||
|     time.tm_min = calendar_time.minute; | ||||
|     time.tm_sec = calendar_time.second; | ||||
|  | ||||
|     std::time_t epoch_time = std::mktime(&time); | ||||
|     return static_cast<u64>(epoch_time); | ||||
| } | ||||
|  | ||||
| class ISystemClock final : public ServiceFramework<ISystemClock> { | ||||
| public: | ||||
|     ISystemClock() : ServiceFramework("ISystemClock") { | ||||
| @@ -80,8 +118,8 @@ public: | ||||
|             {5, nullptr, "GetTimeZoneRuleVersion"}, | ||||
|             {100, &ITimeZoneService::ToCalendarTime, "ToCalendarTime"}, | ||||
|             {101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"}, | ||||
|             {201, nullptr, "ToPosixTime"}, | ||||
|             {202, nullptr, "ToPosixTimeWithMyRule"}, | ||||
|             {201, &ITimeZoneService::ToPosixTime, "ToPosixTime"}, | ||||
|             {202, &ITimeZoneService::ToPosixTimeWithMyRule, "ToPosixTimeWithMyRule"}, | ||||
|         }; | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| @@ -151,24 +189,29 @@ private: | ||||
|         rb.PushRaw(additional_info); | ||||
|     } | ||||
|  | ||||
|     void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, | ||||
|                          CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { | ||||
|         std::time_t t(posix_time); | ||||
|         std::tm* tm = std::localtime(&t); | ||||
|         if (!tm) { | ||||
|             return; | ||||
|         } | ||||
|         calendar_time.year = tm->tm_year + 1900; | ||||
|         calendar_time.month = tm->tm_mon + 1; | ||||
|         calendar_time.day = tm->tm_mday; | ||||
|         calendar_time.hour = tm->tm_hour; | ||||
|         calendar_time.minute = tm->tm_min; | ||||
|         calendar_time.second = tm->tm_sec; | ||||
|     void ToPosixTime(Kernel::HLERequestContext& ctx) { | ||||
|         // TODO(ogniK): Figure out how to handle multiple times | ||||
|         LOG_WARNING(Service_Time, "(STUBBED) called"); | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         auto calendar_time = rp.PopRaw<CalendarTime>(); | ||||
|         auto posix_time = CalendarToPosix(calendar_time, {}); | ||||
|  | ||||
|         additional_info.day_of_week = tm->tm_wday; | ||||
|         additional_info.day_of_year = tm->tm_yday; | ||||
|         std::memcpy(additional_info.name.data(), "UTC", sizeof("UTC")); | ||||
|         additional_info.utc_offset = 0; | ||||
|         IPC::ResponseBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.PushRaw<u32>(1); // Amount of times we're returning | ||||
|         ctx.WriteBuffer(&posix_time, sizeof(u64)); | ||||
|     } | ||||
|  | ||||
|     void ToPosixTimeWithMyRule(Kernel::HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_Time, "(STUBBED) called"); | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         auto calendar_time = rp.PopRaw<CalendarTime>(); | ||||
|         auto posix_time = CalendarToPosix(calendar_time, {}); | ||||
|  | ||||
|         IPC::ResponseBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.PushRaw<u32>(1); // Amount of times we're returning | ||||
|         ctx.WriteBuffer(&posix_time, sizeof(u64)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @@ -207,6 +250,55 @@ void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& c | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
| } | ||||
|  | ||||
| void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|  | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     auto unknown_u8 = rp.PopRaw<u8>(); | ||||
|  | ||||
|     ClockSnapshot clock_snapshot{}; | ||||
|  | ||||
|     const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::seconds>( | ||||
|                                    std::chrono::system_clock::now().time_since_epoch()) | ||||
|                                    .count()}; | ||||
|     CalendarTime calendar_time{}; | ||||
|     const std::time_t time(time_since_epoch); | ||||
|     const std::tm* tm = std::localtime(&time); | ||||
|     if (tm == nullptr) { | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultCode(-1)); // TODO(ogniK): Find appropriate error code | ||||
|         return; | ||||
|     } | ||||
|     SteadyClockTimePoint steady_clock_time_point{CoreTiming::cyclesToMs(CoreTiming::GetTicks()) / | ||||
|                                                  1000}; | ||||
|  | ||||
|     LocationName location_name{"UTC"}; | ||||
|     calendar_time.year = tm->tm_year + 1900; | ||||
|     calendar_time.month = tm->tm_mon + 1; | ||||
|     calendar_time.day = tm->tm_mday; | ||||
|     calendar_time.hour = tm->tm_hour; | ||||
|     calendar_time.minute = tm->tm_min; | ||||
|     calendar_time.second = tm->tm_sec; | ||||
|     clock_snapshot.system_posix_time = time_since_epoch; | ||||
|     clock_snapshot.network_posix_time = time_since_epoch; | ||||
|     clock_snapshot.system_calendar_time = calendar_time; | ||||
|     clock_snapshot.network_calendar_time = calendar_time; | ||||
|  | ||||
|     CalendarAdditionalInfo additional_info{}; | ||||
|     PosixToCalendar(time_since_epoch, calendar_time, additional_info, {}); | ||||
|  | ||||
|     clock_snapshot.system_calendar_info = additional_info; | ||||
|     clock_snapshot.network_calendar_info = additional_info; | ||||
|  | ||||
|     clock_snapshot.steady_clock_timepoint = steady_clock_time_point; | ||||
|     clock_snapshot.location_name = location_name; | ||||
|     clock_snapshot.clock_auto_adjustment_enabled = 1; | ||||
|     clock_snapshot.ipc_u8 = unknown_u8; | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     ctx.WriteBuffer(&clock_snapshot, sizeof(ClockSnapshot)); | ||||
| } | ||||
|  | ||||
| Module::Interface::Interface(std::shared_ptr<Module> time, const char* name) | ||||
|     : ServiceFramework(name), time(std::move(time)) {} | ||||
|  | ||||
|   | ||||
| @@ -5,6 +5,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <array> | ||||
| #include "common/common_funcs.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Service::Time { | ||||
| @@ -53,6 +54,23 @@ struct SystemClockContext { | ||||
| static_assert(sizeof(SystemClockContext) == 0x20, | ||||
|               "SystemClockContext structure has incorrect size"); | ||||
|  | ||||
| struct ClockSnapshot { | ||||
|     SystemClockContext user_clock_context; | ||||
|     SystemClockContext network_clock_context; | ||||
|     s64_le system_posix_time; | ||||
|     s64_le network_posix_time; | ||||
|     CalendarTime system_calendar_time; | ||||
|     CalendarTime network_calendar_time; | ||||
|     CalendarAdditionalInfo system_calendar_info; | ||||
|     CalendarAdditionalInfo network_calendar_info; | ||||
|     SteadyClockTimePoint steady_clock_timepoint; | ||||
|     LocationName location_name; | ||||
|     u8 clock_auto_adjustment_enabled; | ||||
|     u8 ipc_u8; | ||||
|     INSERT_PADDING_BYTES(2); | ||||
| }; | ||||
| static_assert(sizeof(ClockSnapshot) == 0xd0, "ClockSnapshot is an invalid size"); | ||||
|  | ||||
| class Module final { | ||||
| public: | ||||
|     class Interface : public ServiceFramework<Interface> { | ||||
| @@ -65,6 +83,7 @@ public: | ||||
|         void GetStandardSteadyClock(Kernel::HLERequestContext& ctx); | ||||
|         void GetTimeZoneService(Kernel::HLERequestContext& ctx); | ||||
|         void GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx); | ||||
|         void GetClockSnapshot(Kernel::HLERequestContext& ctx); | ||||
|  | ||||
|     protected: | ||||
|         std::shared_ptr<Module> time; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei