From 4f78f5c0df0a106cab891c7f7229563e7f5a69e1 Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 10 Nov 2018 01:25:56 +1100 Subject: [PATCH 1/4] Implement GetClockSnapshot Needed by megaman 11 --- src/core/hle/service/time/interface.cpp | 2 +- src/core/hle/service/time/time.cpp | 89 +++++++++++++++++++------ src/core/hle/service/time/time.h | 18 +++++ 3 files changed, 88 insertions(+), 21 deletions(-) diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp index 18a5d71d5..e3cbd7004 100644 --- a/src/core/hle/service/time/interface.cpp +++ b/src/core/hle/service/time/interface.cpp @@ -21,7 +21,7 @@ Time::Time(std::shared_ptr 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"}, diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index 28fd8debc..dc504eaac 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -15,6 +15,26 @@ namespace Service::Time { +void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, + CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { + std::time_t time(posix_time); + std::tm* tm = std::localtime(&time); + if (tm == nullptr) { + 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; +} + class ISystemClock final : public ServiceFramework { public: ISystemClock() : ServiceFramework("ISystemClock") { @@ -150,26 +170,6 @@ private: rb.PushRaw(calendar_time); 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; - - 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; - } }; void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { @@ -207,6 +207,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(); + + ClockSnapshot clock_snapshot{}; + + const s64 time_since_epoch{std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count()}; + CalendarTime calendar_time{}; + std::time_t time(time_since_epoch); + 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 time, const char* name) : ServiceFramework(name), time(std::move(time)) {} diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index 5659ecad3..ca30ec60f 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -53,6 +53,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 { @@ -65,6 +82,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 time; From 84c6134264e73945616cf847af149e3d8dec67bc Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 10 Nov 2018 12:31:48 +1100 Subject: [PATCH 2/4] Added consts and static --- src/core/hle/service/time/time.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index dc504eaac..a3b3ffb8a 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -15,10 +15,10 @@ namespace Service::Time { -void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, - CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { - std::time_t time(posix_time); - std::tm* tm = std::localtime(&time); +static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, + CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { + const std::time_t time(posix_time); + const std::tm* tm = std::localtime(&time); if (tm == nullptr) { return; } @@ -219,8 +219,8 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { std::chrono::system_clock::now().time_since_epoch()) .count()}; CalendarTime calendar_time{}; - std::time_t time(time_since_epoch); - std::tm* tm = std::localtime(&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 From ddc242dd516d6af58f16dc3fc089569d2eac093b Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 10 Nov 2018 17:41:57 +1100 Subject: [PATCH 3/4] Added ToPosixTime & ToPosixTimeWithMyRule Added instead of using a seperate PR to prevent conflicts --- src/core/hle/service/time/time.cpp | 43 ++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index a3b3ffb8a..d312bd765 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -35,6 +35,20 @@ static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, additional_info.utc_offset = 0; } +u64 CalendarToPosix(const CalendarTime& calendar_time, 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(epoch_time); +} + class ISystemClock final : public ServiceFramework { public: ISystemClock() : ServiceFramework("ISystemClock") { @@ -100,8 +114,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); } @@ -170,6 +184,31 @@ private: rb.PushRaw(calendar_time); rb.PushRaw(additional_info); } + + 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(); + auto posix_time = CalendarToPosix(calendar_time, {}); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(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(); + auto posix_time = CalendarToPosix(calendar_time, {}); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw(1); // Amount of times we're returning + ctx.WriteBuffer(&posix_time, sizeof(u64)); + } }; void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { From 48cd61d9c865aa0d93789cf05b647b272bccab4e Mon Sep 17 00:00:00 2001 From: David Marcec Date: Sat, 10 Nov 2018 18:07:34 +1100 Subject: [PATCH 4/4] Added maybe_unused --- src/core/hle/service/time/time.cpp | 8 ++++++-- src/core/hle/service/time/time.h | 1 + 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp index d312bd765..85e7b1195 100644 --- a/src/core/hle/service/time/time.cpp +++ b/src/core/hle/service/time/time.cpp @@ -16,10 +16,13 @@ namespace Service::Time { static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, - CalendarAdditionalInfo& additional_info, const TimeZoneRule& /*rule*/) { + 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; @@ -35,7 +38,8 @@ static void PosixToCalendar(u64 posix_time, CalendarTime& calendar_time, additional_info.utc_offset = 0; } -u64 CalendarToPosix(const CalendarTime& calendar_time, const TimeZoneRule& /*rule*/) { +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; diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h index ca30ec60f..77871ae07 100644 --- a/src/core/hle/service/time/time.h +++ b/src/core/hle/service/time/time.h @@ -5,6 +5,7 @@ #pragma once #include +#include "common/common_funcs.h" #include "core/hle/service/service.h" namespace Service::Time {