From fab2607c6bae25f50912b32e1cbbfb5a6191916c Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Sun, 22 Dec 2019 18:10:59 -0500
Subject: [PATCH] service: time: Implement
 IsStandardNetworkSystemClockAccuracySufficient.

---
 src/core/hle/service/time/clock_types.h       | 20 +++++++++++++++++++
 src/core/hle/service/time/interface.cpp       |  2 +-
 .../time/standard_network_system_clock_core.h | 20 +++++++++++++++++++
 src/core/hle/service/time/time.cpp            |  9 +++++++++
 src/core/hle/service/time/time.h              |  1 +
 5 files changed, 51 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/service/time/clock_types.h b/src/core/hle/service/time/clock_types.h
index f2ef3ec538..3d5b0ff1ea 100644
--- a/src/core/hle/service/time/clock_types.h
+++ b/src/core/hle/service/time/clock_types.h
@@ -4,6 +4,8 @@
 
 #pragma once
 
+#include <boost/safe_numerics/safe_integer.hpp>
+
 #include "common/common_funcs.h"
 #include "common/common_types.h"
 #include "common/uuid.h"
@@ -17,6 +19,24 @@ struct SteadyClockTimePoint {
     s64 time_point;
     Common::UUID clock_source_id;
 
+    ResultCode GetSpanBetween(SteadyClockTimePoint other, s64& span) const {
+        span = 0;
+
+        if (clock_source_id != other.clock_source_id) {
+            return ERROR_TIME_MISMATCH;
+        }
+
+        const boost::safe_numerics::safe<s64> this_time_point{time_point};
+        const boost::safe_numerics::safe<s64> other_time_point{other.time_point};
+        try {
+            span = other_time_point - this_time_point;
+        } catch (const std::exception&) {
+            return ERROR_OVERFLOW;
+        }
+
+        return RESULT_SUCCESS;
+    }
+
     static SteadyClockTimePoint GetRandom() {
         return {0, Common::UUID::Generate()};
     }
diff --git a/src/core/hle/service/time/interface.cpp b/src/core/hle/service/time/interface.cpp
index b1307a434d..0bc90b1838 100644
--- a/src/core/hle/service/time/interface.cpp
+++ b/src/core/hle/service/time/interface.cpp
@@ -24,7 +24,7 @@ Time::Time(std::shared_ptr<Module> module, Core::System& system, const char* nam
         {100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
         {101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
         {102, nullptr, "GetStandardUserSystemClockInitialYear"},
-        {200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
+        {200, &Time::IsStandardNetworkSystemClockAccuracySufficient, "IsStandardNetworkSystemClockAccuracySufficient"},
         {201, nullptr, "GetStandardUserSystemClockAutomaticCorrectionUpdatedTime"},
         {300, &Time::CalculateMonotonicSystemClockBaseTimePoint, "CalculateMonotonicSystemClockBaseTimePoint"},
         {400, &Time::GetClockSnapshot, "GetClockSnapshot"},
diff --git a/src/core/hle/service/time/standard_network_system_clock_core.h b/src/core/hle/service/time/standard_network_system_clock_core.h
index 4672851608..3f505c37c0 100644
--- a/src/core/hle/service/time/standard_network_system_clock_core.h
+++ b/src/core/hle/service/time/standard_network_system_clock_core.h
@@ -8,6 +8,10 @@
 #include "core/hle/service/time/steady_clock_core.h"
 #include "core/hle/service/time/system_clock_core.h"
 
+namespace Core {
+class System;
+}
+
 namespace Service::Time::Clock {
 
 class StandardNetworkSystemClockCore final : public SystemClockCore {
@@ -19,6 +23,22 @@ public:
         standard_network_clock_sufficient_accuracy = value;
     }
 
+    bool IsStandardNetworkSystemClockAccuracySufficient(Core::System& system) {
+        SystemClockContext context{};
+        if (GetClockContext(system, context) != RESULT_SUCCESS) {
+            return {};
+        }
+
+        s64 span{};
+        if (context.steady_time_point.GetSpanBetween(
+                GetSteadyClockCore().GetCurrentTimePoint(system), span) != RESULT_SUCCESS) {
+            return {};
+        }
+
+        return TimeSpanType{span}.nanoseconds <
+               standard_network_clock_sufficient_accuracy.nanoseconds;
+    }
+
 private:
     TimeSpanType standard_network_clock_sufficient_accuracy{};
 };
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index 970aed0bbb..2053fa0789 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -199,6 +199,15 @@ void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
     rb.PushIpcInterface<ITimeZoneService>(module->GetTimeManager().GetTimeZoneContentManager());
 }
 
+void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(
+    Kernel::HLERequestContext& ctx) {
+    LOG_DEBUG(Service_Time, "called");
+    auto& clock_core{module->GetTimeManager().GetStandardNetworkSystemClockCore()};
+    IPC::ResponseBuilder rb{ctx, 3};
+    rb.Push(RESULT_SUCCESS);
+    rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system));
+}
+
 void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) {
     LOG_DEBUG(Service_Time, "called");
 
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 7b77ac7ea9..0b3cda6aa3 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -27,6 +27,7 @@ public:
         void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx);
         void GetStandardSteadyClock(Kernel::HLERequestContext& ctx);
         void GetTimeZoneService(Kernel::HLERequestContext& ctx);
+        void IsStandardNetworkSystemClockAccuracySufficient(Kernel::HLERequestContext& ctx);
         void CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx);
         void GetClockSnapshot(Kernel::HLERequestContext& ctx);
         void GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx);
-- 
GitLab