// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "common/common_funcs.h" #include "common/common_types.h" #include "common/uuid.h" #include "core/hle/service/time/errors.h" #include "core/hle/service/time/time_zone_types.h" namespace Service::Time::Clock { enum class TimeType : u8 { UserSystemClock, NetworkSystemClock, LocalSystemClock, }; /// https://switchbrew.org/wiki/Glue_services#SteadyClockTimePoint struct SteadyClockTimePoint { s64 time_point; Common::UUID clock_source_id; Result GetSpanBetween(SteadyClockTimePoint other, s64& span) const { span = 0; if (clock_source_id != other.clock_source_id) { return ERROR_TIME_MISMATCH; } span = other.time_point - time_point; return ResultSuccess; } static SteadyClockTimePoint GetRandom() { return {0, Common::UUID::MakeRandom()}; } }; static_assert(sizeof(SteadyClockTimePoint) == 0x18, "SteadyClockTimePoint is incorrect size"); static_assert(std::is_trivially_copyable_v, "SteadyClockTimePoint must be trivially copyable"); struct SteadyClockContext { u64 internal_offset; Common::UUID steady_time_point; }; static_assert(sizeof(SteadyClockContext) == 0x18, "SteadyClockContext is incorrect size"); static_assert(std::is_trivially_copyable_v, "SteadyClockContext must be trivially copyable"); struct SystemClockContext { s64 offset; SteadyClockTimePoint steady_time_point; }; static_assert(sizeof(SystemClockContext) == 0x20, "SystemClockContext is incorrect size"); static_assert(std::is_trivially_copyable_v, "SystemClockContext must be trivially copyable"); /// https://switchbrew.org/wiki/Glue_services#TimeSpanType struct TimeSpanType { s64 nanoseconds{}; static constexpr s64 ns_per_second{1000000000ULL}; s64 ToSeconds() const { return nanoseconds / ns_per_second; } static TimeSpanType FromSeconds(s64 seconds) { return {seconds * ns_per_second}; } static TimeSpanType FromTicks(u64 ticks, u64 frequency) { return FromSeconds(static_cast(ticks) / static_cast(frequency)); } }; static_assert(sizeof(TimeSpanType) == 8, "TimeSpanType is incorrect size"); struct ClockSnapshot { SystemClockContext user_context; SystemClockContext network_context; s64 user_time; s64 network_time; TimeZone::CalendarTime user_calendar_time; TimeZone::CalendarTime network_calendar_time; TimeZone::CalendarAdditionalInfo user_calendar_additional_time; TimeZone::CalendarAdditionalInfo network_calendar_additional_time; SteadyClockTimePoint steady_clock_time_point; TimeZone::LocationName location_name; u8 is_automatic_correction_enabled; TimeType type; INSERT_PADDING_BYTES_NOINIT(0x2); static Result GetCurrentTime(s64& current_time, const SteadyClockTimePoint& steady_clock_time_point, const SystemClockContext& context) { if (steady_clock_time_point.clock_source_id != context.steady_time_point.clock_source_id) { current_time = 0; return ERROR_TIME_MISMATCH; } current_time = steady_clock_time_point.time_point + context.offset; return ResultSuccess; } }; static_assert(sizeof(ClockSnapshot) == 0xD0, "ClockSnapshot is incorrect size"); } // namespace Service::Time::Clock