/* * Copyright (c) Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <stratosphere.hpp> #if defined(ATMOSPHERE_OS_HORIZON) extern "C" { extern TimeServiceType __nx_time_service_type; } #endif namespace ams::time { namespace { enum InitializeMode { InitializeMode_None, InitializeMode_Normal, InitializeMode_Menu, InitializeMode_System, InitializeMode_Repair, InitializeMode_SystemUser, }; constinit u32 g_initialize_count = 0; constinit InitializeMode g_initialize_mode = InitializeMode_None; constinit os::SdkMutex g_initialize_mutex; Result InitializeImpl(InitializeMode mode) { std::scoped_lock lk(g_initialize_mutex); if (g_initialize_count > 0) { AMS_ABORT_UNLESS(mode == g_initialize_mode); g_initialize_count++; R_SUCCEED(); } #if defined(ATMOSPHERE_OS_HORIZON) switch (mode) { case InitializeMode_Normal: __nx_time_service_type = ::TimeServiceType_User; break; case InitializeMode_Menu: __nx_time_service_type = ::TimeServiceType_Menu; break; case InitializeMode_System: __nx_time_service_type = ::TimeServiceType_System; break; case InitializeMode_Repair: __nx_time_service_type = ::TimeServiceType_Repair; break; case InitializeMode_SystemUser: __nx_time_service_type = ::TimeServiceType_SystemUser; break; AMS_UNREACHABLE_DEFAULT_CASE(); } R_TRY(::timeInitialize()); #else // TODO: Real AMS_ABORT("TODO"); #endif g_initialize_count++; g_initialize_mode = mode; R_SUCCEED(); } } Result Initialize() { R_RETURN(InitializeImpl(InitializeMode_Normal)); } Result InitializeForSystem() { R_RETURN(InitializeImpl(InitializeMode_System)); } Result InitializeForSystemUser() { if (hos::GetVersion() >= hos::Version_9_0_0) { R_RETURN(InitializeImpl(InitializeMode_SystemUser)); } else { R_RETURN(InitializeImpl(InitializeMode_Normal)); } } Result Finalize() { std::scoped_lock lk(g_initialize_mutex); if (g_initialize_count > 0) { if ((--g_initialize_count) == 0) { #if defined(ATMOSPHERE_OS_HORIZON) ::timeExit(); #else // TODO: Real AMS_ABORT("TODO"); #endif g_initialize_mode = InitializeMode_None; } } R_SUCCEED(); } bool IsInitialized() { std::scoped_lock lk(g_initialize_mutex); return g_initialize_count > 0; } bool IsValidDate(int year, int month, int day) { return impl::util::IsValidDate(year, month, day); } Result GetElapsedSecondsBetween(s64 *out, const SteadyClockTimePoint &from, const SteadyClockTimePoint &to) { R_RETURN(impl::util::GetSpanBetween(out, from, to)); } }