mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	service: time: Update current time with changes to RTC setting.
- This can be used to advance time, e.g. for Pokemon Sword/Shield pokejobs.
This commit is contained in:
		
							parent
							
								
									4c348f4069
								
							
						
					
					
						commit
						62c6c9f6a6
					
				| @ -40,6 +40,7 @@ | ||||
| #include "core/hle/service/lm/manager.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/hle/service/sm/sm.h" | ||||
| #include "core/hle/service/time/time_manager.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/memory.h" | ||||
| #include "core/memory/cheat_engine.h" | ||||
| @ -121,7 +122,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, | ||||
| struct System::Impl { | ||||
|     explicit Impl(System& system) | ||||
|         : kernel{system}, fs_controller{system}, memory{system}, | ||||
|           cpu_manager{system}, reporter{system}, applet_manager{system} {} | ||||
|           cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {} | ||||
| 
 | ||||
|     ResultStatus Run() { | ||||
|         status = ResultStatus::Success; | ||||
| @ -189,6 +190,9 @@ struct System::Impl { | ||||
|             return ResultStatus::ErrorVideoCore; | ||||
|         } | ||||
| 
 | ||||
|         // Initialize time manager, which must happen after kernel is created
 | ||||
|         time_manager.Initialize(); | ||||
| 
 | ||||
|         is_powered_on = true; | ||||
|         exit_lock = false; | ||||
| 
 | ||||
| @ -387,6 +391,7 @@ struct System::Impl { | ||||
|     /// Service State
 | ||||
|     Service::Glue::ARPManager arp_manager; | ||||
|     Service::LM::Manager lm_manager{reporter}; | ||||
|     Service::Time::TimeManager time_manager; | ||||
| 
 | ||||
|     /// Service manager
 | ||||
|     std::shared_ptr<Service::SM::ServiceManager> service_manager; | ||||
| @ -717,6 +722,14 @@ const Service::LM::Manager& System::GetLogManager() const { | ||||
|     return impl->lm_manager; | ||||
| } | ||||
| 
 | ||||
| Service::Time::TimeManager& System::GetTimeManager() { | ||||
|     return impl->time_manager; | ||||
| } | ||||
| 
 | ||||
| const Service::Time::TimeManager& System::GetTimeManager() const { | ||||
|     return impl->time_manager; | ||||
| } | ||||
| 
 | ||||
| void System::SetExitLock(bool locked) { | ||||
|     impl->exit_lock = locked; | ||||
| } | ||||
|  | ||||
| @ -69,6 +69,10 @@ namespace SM { | ||||
| class ServiceManager; | ||||
| } // namespace SM
 | ||||
| 
 | ||||
| namespace Time { | ||||
| class TimeManager; | ||||
| } // namespace Time
 | ||||
| 
 | ||||
| } // namespace Service
 | ||||
| 
 | ||||
| namespace Tegra { | ||||
| @ -361,6 +365,10 @@ public: | ||||
| 
 | ||||
|     const Service::LM::Manager& GetLogManager() const; | ||||
| 
 | ||||
|     Service::Time::TimeManager& GetTimeManager(); | ||||
| 
 | ||||
|     const Service::Time::TimeManager& GetTimeManager() const; | ||||
| 
 | ||||
|     void SetExitLock(bool locked); | ||||
| 
 | ||||
|     bool GetExitLock() const; | ||||
|  | ||||
| @ -10,6 +10,7 @@ | ||||
| #include "core/hle/ipc_helpers.h" | ||||
| #include "core/hle/kernel/client_port.h" | ||||
| #include "core/hle/kernel/client_session.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/scheduler.h" | ||||
| #include "core/hle/service/time/interface.h" | ||||
| #include "core/hle/service/time/time.h" | ||||
| @ -125,7 +126,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal( | ||||
|     Kernel::Thread* thread, Clock::SystemClockContext user_context, | ||||
|     Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) { | ||||
| 
 | ||||
|     auto& time_manager{module->GetTimeManager()}; | ||||
|     auto& time_manager{system.GetTimeManager()}; | ||||
| 
 | ||||
|     clock_snapshot.is_automatic_correction_enabled = | ||||
|         time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); | ||||
| @ -182,7 +183,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardUserSystemClockCore(), | ||||
|     rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardUserSystemClockCore(), | ||||
|                                       system); | ||||
| } | ||||
| 
 | ||||
| @ -190,7 +191,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext& | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardNetworkSystemClockCore(), | ||||
|     rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardNetworkSystemClockCore(), | ||||
|                                       system); | ||||
| } | ||||
| 
 | ||||
| @ -198,29 +199,28 @@ void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<ISteadyClock>(module->GetTimeManager().GetStandardSteadyClockCore(), | ||||
|                                       system); | ||||
|     rb.PushIpcInterface<ISteadyClock>(system.GetTimeManager().GetStandardSteadyClockCore(), system); | ||||
| } | ||||
| 
 | ||||
| void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<ITimeZoneService>(module->GetTimeManager().GetTimeZoneContentManager()); | ||||
|     rb.PushIpcInterface<ITimeZoneService>(system.GetTimeManager().GetTimeZoneContentManager()); | ||||
| } | ||||
| 
 | ||||
| void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardLocalSystemClockCore(), | ||||
|     rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardLocalSystemClockCore(), | ||||
|                                       system); | ||||
| } | ||||
| 
 | ||||
| void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( | ||||
|     Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|     auto& clock_core{module->GetTimeManager().GetStandardNetworkSystemClockCore()}; | ||||
|     auto& clock_core{system.GetTimeManager().GetStandardNetworkSystemClockCore()}; | ||||
|     IPC::ResponseBuilder rb{ctx, 3}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system)); | ||||
| @ -229,7 +229,7 @@ void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( | ||||
| void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
| 
 | ||||
|     auto& steady_clock_core{module->GetTimeManager().GetStandardSteadyClockCore()}; | ||||
|     auto& steady_clock_core{system.GetTimeManager().GetStandardSteadyClockCore()}; | ||||
|     if (!steady_clock_core.IsInitialized()) { | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ERROR_UNINITIALIZED_CLOCK); | ||||
| @ -262,8 +262,8 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | ||||
| 
 | ||||
|     Clock::SystemClockContext user_context{}; | ||||
|     if (const ResultCode result{ | ||||
|             module->GetTimeManager().GetStandardUserSystemClockCore().GetClockContext( | ||||
|                 system, user_context)}; | ||||
|             system.GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(system, | ||||
|                                                                                      user_context)}; | ||||
|         result.IsError()) { | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(result); | ||||
| @ -271,7 +271,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) { | ||||
|     } | ||||
|     Clock::SystemClockContext network_context{}; | ||||
|     if (const ResultCode result{ | ||||
|             module->GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( | ||||
|             system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( | ||||
|                 system, network_context)}; | ||||
|         result.IsError()) { | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
| @ -372,7 +372,7 @@ void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& c | ||||
|     LOG_DEBUG(Service_Time, "called"); | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushCopyObjects(module->GetTimeManager().GetSharedMemory().GetSharedMemoryHolder()); | ||||
|     rb.PushCopyObjects(SharedFrom(&system.Kernel().GetTimeSharedMem())); | ||||
| } | ||||
| 
 | ||||
| Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) | ||||
| @ -381,7 +381,7 @@ Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& syste | ||||
| Module::Interface::~Interface() = default; | ||||
| 
 | ||||
| void InstallInterfaces(Core::System& system) { | ||||
|     auto module{std::make_shared<Module>(system)}; | ||||
|     auto module{std::make_shared<Module>()}; | ||||
|     std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager()); | ||||
|     std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager()); | ||||
|     std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager()); | ||||
|  | ||||
| @ -16,7 +16,7 @@ namespace Service::Time { | ||||
| 
 | ||||
| class Module final { | ||||
| public: | ||||
|     Module(Core::System& system) : time_manager{system} {} | ||||
|     Module() = default; | ||||
| 
 | ||||
|     class Interface : public ServiceFramework<Interface> { | ||||
|     public: | ||||
| @ -46,13 +46,6 @@ public: | ||||
|         std::shared_ptr<Module> module; | ||||
|         Core::System& system; | ||||
|     }; | ||||
| 
 | ||||
|     TimeManager& GetTimeManager() { | ||||
|         return time_manager; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     TimeManager time_manager; | ||||
| }; | ||||
| 
 | ||||
| /// Registers all Time services with the specified service manager.
 | ||||
|  | ||||
| @ -22,7 +22,277 @@ static std::chrono::seconds GetSecondsSinceEpoch() { | ||||
|            Settings::values.custom_rtc_differential; | ||||
| } | ||||
| 
 | ||||
| static s64 GetExternalTimeZoneOffset() { | ||||
| static s64 GetExternalRtcValue() { | ||||
|     return GetSecondsSinceEpoch().count() + TimeManager::GetExternalTimeZoneOffset(); | ||||
| } | ||||
| 
 | ||||
| struct TimeManager::Impl final { | ||||
|     explicit Impl(Core::System& system) | ||||
|         : shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core}, | ||||
|           standard_network_system_clock_core{standard_steady_clock_core}, | ||||
|           standard_user_system_clock_core{standard_local_system_clock_core, | ||||
|                                           standard_network_system_clock_core, system}, | ||||
|           ephemeral_network_system_clock_core{tick_based_steady_clock_core}, | ||||
|           local_system_clock_context_writer{ | ||||
|               std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)}, | ||||
|           network_system_clock_context_writer{ | ||||
|               std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)}, | ||||
|           ephemeral_network_system_clock_context_writer{ | ||||
|               std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()}, | ||||
|           time_zone_content_manager{system} { | ||||
| 
 | ||||
|         const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; | ||||
|         SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {}); | ||||
|         SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); | ||||
|         SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy); | ||||
|         SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom()); | ||||
|         SetupEphemeralNetworkSystemClock(); | ||||
|     } | ||||
| 
 | ||||
|     ~Impl() = default; | ||||
| 
 | ||||
|     Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() { | ||||
|         return standard_steady_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const { | ||||
|         return standard_steady_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() { | ||||
|         return standard_local_system_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const { | ||||
|         return standard_local_system_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() { | ||||
|         return standard_network_system_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const { | ||||
|         return standard_network_system_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() { | ||||
|         return standard_user_system_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const { | ||||
|         return standard_user_system_clock_core; | ||||
|     } | ||||
| 
 | ||||
|     TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() { | ||||
|         return time_zone_content_manager; | ||||
|     } | ||||
| 
 | ||||
|     const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const { | ||||
|         return time_zone_content_manager; | ||||
|     } | ||||
| 
 | ||||
|     SharedMemory& GetSharedMemory() { | ||||
|         return shared_memory; | ||||
|     } | ||||
| 
 | ||||
|     const SharedMemory& GetSharedMemory() const { | ||||
|         return shared_memory; | ||||
|     } | ||||
| 
 | ||||
|     void SetupTimeZoneManager(std::string location_name, | ||||
|                               Clock::SteadyClockTimePoint time_zone_updated_time_point, | ||||
|                               std::size_t total_location_name_count, u128 time_zone_rule_version, | ||||
|                               FileSys::VirtualFile& vfs_file) { | ||||
|         if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( | ||||
|                 location_name, vfs_file) != RESULT_SUCCESS) { | ||||
|             UNREACHABLE(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point); | ||||
|         time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount( | ||||
|             total_location_name_count); | ||||
|         time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion( | ||||
|             time_zone_rule_version); | ||||
|         time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized(); | ||||
|     } | ||||
| 
 | ||||
|     static s64 GetExternalTimeZoneOffset() { | ||||
|         // With "auto" timezone setting, we use the external system's timezone offset
 | ||||
|         if (Settings::GetTimeZoneString() == "auto") { | ||||
|             return Common::TimeZone::GetCurrentOffsetSeconds().count(); | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
| 
 | ||||
|     void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, | ||||
|                                   Clock::TimeSpanType setup_value, | ||||
|                                   Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) { | ||||
|         standard_steady_clock_core.SetClockSourceId(clock_source_id); | ||||
|         standard_steady_clock_core.SetSetupValue(setup_value); | ||||
|         standard_steady_clock_core.SetInternalOffset(internal_offset); | ||||
|         standard_steady_clock_core.MarkAsInitialized(); | ||||
| 
 | ||||
|         const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)}; | ||||
|         shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point); | ||||
|     } | ||||
| 
 | ||||
|     void SetupStandardLocalSystemClock(Core::System& system, | ||||
|                                        Clock::SystemClockContext clock_context, s64 posix_time) { | ||||
|         standard_local_system_clock_core.SetUpdateCallbackInstance( | ||||
|             local_system_clock_context_writer); | ||||
| 
 | ||||
|         const auto current_time_point{ | ||||
|             standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)}; | ||||
|         if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) { | ||||
|             standard_local_system_clock_core.SetSystemClockContext(clock_context); | ||||
|         } else { | ||||
|             if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != | ||||
|                 RESULT_SUCCESS) { | ||||
|                 UNREACHABLE(); | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         standard_local_system_clock_core.MarkAsInitialized(); | ||||
|     } | ||||
| 
 | ||||
|     void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context, | ||||
|                                          Clock::TimeSpanType sufficient_accuracy) { | ||||
|         standard_network_system_clock_core.SetUpdateCallbackInstance( | ||||
|             network_system_clock_context_writer); | ||||
| 
 | ||||
|         if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != | ||||
|             RESULT_SUCCESS) { | ||||
|             UNREACHABLE(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy( | ||||
|             sufficient_accuracy); | ||||
|         standard_network_system_clock_core.MarkAsInitialized(); | ||||
|     } | ||||
| 
 | ||||
|     void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled, | ||||
|                                       Clock::SteadyClockTimePoint steady_clock_time_point) { | ||||
|         if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( | ||||
|                 system, is_automatic_correction_enabled) != RESULT_SUCCESS) { | ||||
|             UNREACHABLE(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point); | ||||
|         standard_user_system_clock_core.MarkAsInitialized(); | ||||
|         shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled); | ||||
|     } | ||||
| 
 | ||||
|     void SetupEphemeralNetworkSystemClock() { | ||||
|         ephemeral_network_system_clock_core.SetUpdateCallbackInstance( | ||||
|             ephemeral_network_system_clock_context_writer); | ||||
|         ephemeral_network_system_clock_core.MarkAsInitialized(); | ||||
|     } | ||||
| 
 | ||||
|     void UpdateLocalSystemClockTime(Core::System& system, s64 posix_time) { | ||||
|         const auto timespan{Service::Time::Clock::TimeSpanType::FromSeconds(posix_time)}; | ||||
|         if (GetStandardLocalSystemClockCore() | ||||
|                 .SetCurrentTime(system, timespan.ToSeconds()) | ||||
|                 .IsError()) { | ||||
|             UNREACHABLE(); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     SharedMemory shared_memory; | ||||
| 
 | ||||
|     Clock::StandardSteadyClockCore standard_steady_clock_core; | ||||
|     Clock::TickBasedSteadyClockCore tick_based_steady_clock_core; | ||||
|     Clock::StandardLocalSystemClockCore standard_local_system_clock_core; | ||||
|     Clock::StandardNetworkSystemClockCore standard_network_system_clock_core; | ||||
|     Clock::StandardUserSystemClockCore standard_user_system_clock_core; | ||||
|     Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core; | ||||
| 
 | ||||
|     std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer; | ||||
|     std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer; | ||||
|     std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter> | ||||
|         ephemeral_network_system_clock_context_writer; | ||||
| 
 | ||||
|     TimeZone::TimeZoneContentManager time_zone_content_manager; | ||||
| }; | ||||
| 
 | ||||
| TimeManager::TimeManager(Core::System& system) : system{system} {} | ||||
| 
 | ||||
| TimeManager::~TimeManager() = default; | ||||
| 
 | ||||
| void TimeManager::Initialize() { | ||||
|     impl = std::make_unique<Impl>(system); | ||||
| 
 | ||||
|     // Time zones can only be initialized after impl is valid
 | ||||
|     impl->time_zone_content_manager.Initialize(*this); | ||||
| } | ||||
| 
 | ||||
| Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() { | ||||
|     return impl->standard_steady_clock_core; | ||||
| } | ||||
| 
 | ||||
| const Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() const { | ||||
|     return impl->standard_steady_clock_core; | ||||
| } | ||||
| 
 | ||||
| Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() { | ||||
|     return impl->standard_local_system_clock_core; | ||||
| } | ||||
| 
 | ||||
| const Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() const { | ||||
|     return impl->standard_local_system_clock_core; | ||||
| } | ||||
| 
 | ||||
| Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore() { | ||||
|     return impl->standard_network_system_clock_core; | ||||
| } | ||||
| 
 | ||||
| const Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore() | ||||
|     const { | ||||
|     return impl->standard_network_system_clock_core; | ||||
| } | ||||
| 
 | ||||
| Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() { | ||||
|     return impl->standard_user_system_clock_core; | ||||
| } | ||||
| 
 | ||||
| const Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() const { | ||||
|     return impl->standard_user_system_clock_core; | ||||
| } | ||||
| 
 | ||||
| TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() { | ||||
|     return impl->time_zone_content_manager; | ||||
| } | ||||
| 
 | ||||
| const TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() const { | ||||
|     return impl->time_zone_content_manager; | ||||
| } | ||||
| 
 | ||||
| SharedMemory& TimeManager::GetSharedMemory() { | ||||
|     return impl->shared_memory; | ||||
| } | ||||
| 
 | ||||
| const SharedMemory& TimeManager::GetSharedMemory() const { | ||||
|     return impl->shared_memory; | ||||
| } | ||||
| 
 | ||||
| void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) { | ||||
|     impl->UpdateLocalSystemClockTime(system, posix_time); | ||||
| } | ||||
| 
 | ||||
| void TimeManager::SetupTimeZoneManager(std::string location_name, | ||||
|                                        Clock::SteadyClockTimePoint time_zone_updated_time_point, | ||||
|                                        std::size_t total_location_name_count, | ||||
|                                        u128 time_zone_rule_version, | ||||
|                                        FileSys::VirtualFile& vfs_file) { | ||||
|     impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point, | ||||
|                                total_location_name_count, time_zone_rule_version, vfs_file); | ||||
| } | ||||
| 
 | ||||
| /*static*/ s64 TimeManager::GetExternalTimeZoneOffset() { | ||||
|     // With "auto" timezone setting, we use the external system's timezone offset
 | ||||
|     if (Settings::GetTimeZoneString() == "auto") { | ||||
|         return Common::TimeZone::GetCurrentOffsetSeconds().count(); | ||||
| @ -30,117 +300,4 @@ static s64 GetExternalTimeZoneOffset() { | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| static s64 GetExternalRtcValue() { | ||||
|     return GetSecondsSinceEpoch().count() + GetExternalTimeZoneOffset(); | ||||
| } | ||||
| 
 | ||||
| TimeManager::TimeManager(Core::System& system) | ||||
|     : shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core}, | ||||
|       standard_network_system_clock_core{standard_steady_clock_core}, | ||||
|       standard_user_system_clock_core{standard_local_system_clock_core, | ||||
|                                       standard_network_system_clock_core, system}, | ||||
|       ephemeral_network_system_clock_core{tick_based_steady_clock_core}, | ||||
|       local_system_clock_context_writer{ | ||||
|           std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)}, | ||||
|       network_system_clock_context_writer{ | ||||
|           std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)}, | ||||
|       ephemeral_network_system_clock_context_writer{ | ||||
|           std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()}, | ||||
|       time_zone_content_manager{*this, system} { | ||||
| 
 | ||||
|     const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())}; | ||||
|     SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {}); | ||||
|     SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds()); | ||||
|     SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy); | ||||
|     SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom()); | ||||
|     SetupEphemeralNetworkSystemClock(); | ||||
| } | ||||
| 
 | ||||
| TimeManager::~TimeManager() = default; | ||||
| 
 | ||||
| void TimeManager::SetupTimeZoneManager(std::string location_name, | ||||
|                                        Clock::SteadyClockTimePoint time_zone_updated_time_point, | ||||
|                                        std::size_t total_location_name_count, | ||||
|                                        u128 time_zone_rule_version, | ||||
|                                        FileSys::VirtualFile& vfs_file) { | ||||
|     if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( | ||||
|             location_name, vfs_file) != RESULT_SUCCESS) { | ||||
|         UNREACHABLE(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point); | ||||
|     time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount( | ||||
|         total_location_name_count); | ||||
|     time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(time_zone_rule_version); | ||||
|     time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized(); | ||||
| } | ||||
| 
 | ||||
| void TimeManager::SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, | ||||
|                                            Clock::TimeSpanType setup_value, | ||||
|                                            Clock::TimeSpanType internal_offset, | ||||
|                                            bool is_rtc_reset_detected) { | ||||
|     standard_steady_clock_core.SetClockSourceId(clock_source_id); | ||||
|     standard_steady_clock_core.SetSetupValue(setup_value); | ||||
|     standard_steady_clock_core.SetInternalOffset(internal_offset); | ||||
|     standard_steady_clock_core.MarkAsInitialized(); | ||||
| 
 | ||||
|     const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)}; | ||||
|     shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point); | ||||
| } | ||||
| 
 | ||||
| void TimeManager::SetupStandardLocalSystemClock(Core::System& system, | ||||
|                                                 Clock::SystemClockContext clock_context, | ||||
|                                                 s64 posix_time) { | ||||
|     standard_local_system_clock_core.SetUpdateCallbackInstance(local_system_clock_context_writer); | ||||
| 
 | ||||
|     const auto current_time_point{ | ||||
|         standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)}; | ||||
|     if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) { | ||||
|         standard_local_system_clock_core.SetSystemClockContext(clock_context); | ||||
|     } else { | ||||
|         if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != RESULT_SUCCESS) { | ||||
|             UNREACHABLE(); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     standard_local_system_clock_core.MarkAsInitialized(); | ||||
| } | ||||
| 
 | ||||
| void TimeManager::SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context, | ||||
|                                                   Clock::TimeSpanType sufficient_accuracy) { | ||||
|     standard_network_system_clock_core.SetUpdateCallbackInstance( | ||||
|         network_system_clock_context_writer); | ||||
| 
 | ||||
|     if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != RESULT_SUCCESS) { | ||||
|         UNREACHABLE(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy( | ||||
|         sufficient_accuracy); | ||||
|     standard_network_system_clock_core.MarkAsInitialized(); | ||||
| } | ||||
| 
 | ||||
| void TimeManager::SetupStandardUserSystemClock( | ||||
|     Core::System& system, bool is_automatic_correction_enabled, | ||||
|     Clock::SteadyClockTimePoint steady_clock_time_point) { | ||||
|     if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( | ||||
|             system, is_automatic_correction_enabled) != RESULT_SUCCESS) { | ||||
|         UNREACHABLE(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point); | ||||
|     standard_user_system_clock_core.MarkAsInitialized(); | ||||
|     shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled); | ||||
| } | ||||
| 
 | ||||
| void TimeManager::SetupEphemeralNetworkSystemClock() { | ||||
|     ephemeral_network_system_clock_core.SetUpdateCallbackInstance( | ||||
|         ephemeral_network_system_clock_context_writer); | ||||
|     ephemeral_network_system_clock_core.MarkAsInitialized(); | ||||
| } | ||||
| 
 | ||||
| } // namespace Service::Time
 | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "common/time_zone.h" | ||||
| #include "core/file_sys/vfs_types.h" | ||||
| #include "core/hle/service/time/clock_types.h" | ||||
| #include "core/hle/service/time/ephemeral_network_system_clock_core.h" | ||||
| @ -32,86 +33,46 @@ public: | ||||
|     explicit TimeManager(Core::System& system); | ||||
|     ~TimeManager(); | ||||
| 
 | ||||
|     Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() { | ||||
|         return standard_steady_clock_core; | ||||
|     } | ||||
|     void Initialize(); | ||||
| 
 | ||||
|     const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const { | ||||
|         return standard_steady_clock_core; | ||||
|     } | ||||
|     Clock::StandardSteadyClockCore& GetStandardSteadyClockCore(); | ||||
| 
 | ||||
|     Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() { | ||||
|         return standard_local_system_clock_core; | ||||
|     } | ||||
|     const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const; | ||||
| 
 | ||||
|     const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const { | ||||
|         return standard_local_system_clock_core; | ||||
|     } | ||||
|     Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore(); | ||||
| 
 | ||||
|     Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() { | ||||
|         return standard_network_system_clock_core; | ||||
|     } | ||||
|     const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const; | ||||
| 
 | ||||
|     const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const { | ||||
|         return standard_network_system_clock_core; | ||||
|     } | ||||
|     Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore(); | ||||
| 
 | ||||
|     Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() { | ||||
|         return standard_user_system_clock_core; | ||||
|     } | ||||
|     const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const; | ||||
| 
 | ||||
|     const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const { | ||||
|         return standard_user_system_clock_core; | ||||
|     } | ||||
|     Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore(); | ||||
| 
 | ||||
|     TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() { | ||||
|         return time_zone_content_manager; | ||||
|     } | ||||
|     const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const; | ||||
| 
 | ||||
|     const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const { | ||||
|         return time_zone_content_manager; | ||||
|     } | ||||
|     TimeZone::TimeZoneContentManager& GetTimeZoneContentManager(); | ||||
| 
 | ||||
|     SharedMemory& GetSharedMemory() { | ||||
|         return shared_memory; | ||||
|     } | ||||
|     const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const; | ||||
| 
 | ||||
|     const SharedMemory& GetSharedMemory() const { | ||||
|         return shared_memory; | ||||
|     } | ||||
|     void UpdateLocalSystemClockTime(s64 posix_time); | ||||
| 
 | ||||
|     SharedMemory& GetSharedMemory(); | ||||
| 
 | ||||
|     const SharedMemory& GetSharedMemory() const; | ||||
| 
 | ||||
|     void SetupTimeZoneManager(std::string location_name, | ||||
|                               Clock::SteadyClockTimePoint time_zone_updated_time_point, | ||||
|                               std::size_t total_location_name_count, u128 time_zone_rule_version, | ||||
|                               FileSys::VirtualFile& vfs_file); | ||||
| 
 | ||||
|     static s64 GetExternalTimeZoneOffset(); | ||||
| 
 | ||||
| private: | ||||
|     void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, | ||||
|                                   Clock::TimeSpanType setup_value, | ||||
|                                   Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected); | ||||
|     void SetupStandardLocalSystemClock(Core::System& system, | ||||
|                                        Clock::SystemClockContext clock_context, s64 posix_time); | ||||
|     void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context, | ||||
|                                          Clock::TimeSpanType sufficient_accuracy); | ||||
|     void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled, | ||||
|                                       Clock::SteadyClockTimePoint steady_clock_time_point); | ||||
|     void SetupEphemeralNetworkSystemClock(); | ||||
|     Core::System& system; | ||||
| 
 | ||||
|     SharedMemory shared_memory; | ||||
| 
 | ||||
|     Clock::StandardSteadyClockCore standard_steady_clock_core; | ||||
|     Clock::TickBasedSteadyClockCore tick_based_steady_clock_core; | ||||
|     Clock::StandardLocalSystemClockCore standard_local_system_clock_core; | ||||
|     Clock::StandardNetworkSystemClockCore standard_network_system_clock_core; | ||||
|     Clock::StandardUserSystemClockCore standard_user_system_clock_core; | ||||
|     Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core; | ||||
| 
 | ||||
|     std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer; | ||||
|     std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer; | ||||
|     std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter> | ||||
|         ephemeral_network_system_clock_context_writer; | ||||
| 
 | ||||
|     TimeZone::TimeZoneContentManager time_zone_content_manager; | ||||
|     struct Impl; | ||||
|     std::unique_ptr<Impl> impl; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service::Time
 | ||||
|  | ||||
| @ -68,9 +68,10 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) { | ||||
|     return location_name_cache; | ||||
| } | ||||
| 
 | ||||
| TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core::System& system) | ||||
|     : system{system}, location_name_cache{BuildLocationNameCache(system)} { | ||||
| TimeZoneContentManager::TimeZoneContentManager(Core::System& system) | ||||
|     : system{system}, location_name_cache{BuildLocationNameCache(system)} {} | ||||
| 
 | ||||
| void TimeZoneContentManager::Initialize(TimeManager& time_manager) { | ||||
|     std::string location_name; | ||||
|     const auto timezone_setting = Settings::GetTimeZoneString(); | ||||
|     if (timezone_setting == "auto" || timezone_setting == "default") { | ||||
|  | ||||
| @ -21,7 +21,9 @@ namespace Service::Time::TimeZone { | ||||
| 
 | ||||
| class TimeZoneContentManager final { | ||||
| public: | ||||
|     TimeZoneContentManager(TimeManager& time_manager, Core::System& system); | ||||
|     TimeZoneContentManager(Core::System& system); | ||||
| 
 | ||||
|     void Initialize(TimeManager& time_manager); | ||||
| 
 | ||||
|     TimeZoneManager& GetTimeZoneManager() { | ||||
|         return time_zone_manager; | ||||
|  | ||||
| @ -12,6 +12,7 @@ | ||||
| #include "common/assert.h" | ||||
| #include "common/file_util.h" | ||||
| #include "core/core.h" | ||||
| #include "core/hle/service/time/time.h" | ||||
| #include "core/settings.h" | ||||
| #include "ui_configure_system.h" | ||||
| #include "yuzu/configuration/configuration_shared.h" | ||||
| @ -104,6 +105,22 @@ void ConfigureSystem::SetConfiguration() { | ||||
| void ConfigureSystem::ReadSystemSettings() {} | ||||
| 
 | ||||
| void ConfigureSystem::ApplyConfiguration() { | ||||
|     // Allow setting custom RTC even if system is powered on, to allow in-game time to be fast
 | ||||
|     // forwared
 | ||||
|     if (Settings::values.custom_rtc.UsingGlobal()) { | ||||
|         if (ui->custom_rtc_checkbox->isChecked()) { | ||||
|             Settings::values.custom_rtc.SetValue( | ||||
|                 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); | ||||
|             if (Core::System::GetInstance().IsPoweredOn()) { | ||||
|                 const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() + | ||||
|                                      Service::Time::TimeManager::GetExternalTimeZoneOffset()}; | ||||
|                 Core::System::GetInstance().GetTimeManager().UpdateLocalSystemClockTime(posix_time); | ||||
|             } | ||||
|         } else { | ||||
|             Settings::values.custom_rtc.SetValue(std::nullopt); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (!enabled) { | ||||
|         return; | ||||
|     } | ||||
| @ -131,15 +148,6 @@ void ConfigureSystem::ApplyConfiguration() { | ||||
|                 Settings::values.rng_seed.SetValue(std::nullopt); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (Settings::values.custom_rtc.UsingGlobal()) { | ||||
|             if (ui->custom_rtc_checkbox->isChecked()) { | ||||
|                 Settings::values.custom_rtc.SetValue( | ||||
|                     std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch())); | ||||
|             } else { | ||||
|                 Settings::values.custom_rtc.SetValue(std::nullopt); | ||||
|             } | ||||
|         } | ||||
|     } else { | ||||
|         ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, | ||||
|                                                  ui->combo_language); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 bunnei
						bunnei