summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2020-10-22 20:46:54 -0700
committerGravatar GitHub2020-10-22 20:46:54 -0700
commite7042163c85c4cb239b9c65e9b03238987ec36d8 (patch)
treee8054756584af4b9a27af22d22d960f09e7c9473 /src
parentcore: Fix clang build pt.3 (diff)
parentservice: time: Update current time with changes to RTC setting. (diff)
downloadyuzu-e7042163c85c4cb239b9c65e9b03238987ec36d8.tar.gz
yuzu-e7042163c85c4cb239b9c65e9b03238987ec36d8.tar.xz
yuzu-e7042163c85c4cb239b9c65e9b03238987ec36d8.zip
Merge pull request #4792 from bunnei/rtc-fix
service: time: Update current time with changes to RTC setting.
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp15
-rw-r--r--src/core/core.h8
-rw-r--r--src/core/hle/service/time/time.cpp28
-rw-r--r--src/core/hle/service/time/time.h9
-rw-r--r--src/core/hle/service/time/time_manager.cpp359
-rw-r--r--src/core/hle/service/time/time_manager.h85
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.cpp5
-rw-r--r--src/core/hle/service/time/time_zone_content_manager.h4
-rw-r--r--src/yuzu/configuration/configure_system.cpp26
9 files changed, 341 insertions, 198 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 81e8cc338..fde2ccc09 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -40,6 +40,7 @@
40#include "core/hle/service/lm/manager.h" 40#include "core/hle/service/lm/manager.h"
41#include "core/hle/service/service.h" 41#include "core/hle/service/service.h"
42#include "core/hle/service/sm/sm.h" 42#include "core/hle/service/sm/sm.h"
43#include "core/hle/service/time/time_manager.h"
43#include "core/loader/loader.h" 44#include "core/loader/loader.h"
44#include "core/memory.h" 45#include "core/memory.h"
45#include "core/memory/cheat_engine.h" 46#include "core/memory/cheat_engine.h"
@@ -121,7 +122,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
121struct System::Impl { 122struct System::Impl {
122 explicit Impl(System& system) 123 explicit Impl(System& system)
123 : kernel{system}, fs_controller{system}, memory{system}, 124 : kernel{system}, fs_controller{system}, memory{system},
124 cpu_manager{system}, reporter{system}, applet_manager{system} {} 125 cpu_manager{system}, reporter{system}, applet_manager{system}, time_manager{system} {}
125 126
126 ResultStatus Run() { 127 ResultStatus Run() {
127 status = ResultStatus::Success; 128 status = ResultStatus::Success;
@@ -189,6 +190,9 @@ struct System::Impl {
189 return ResultStatus::ErrorVideoCore; 190 return ResultStatus::ErrorVideoCore;
190 } 191 }
191 192
193 // Initialize time manager, which must happen after kernel is created
194 time_manager.Initialize();
195
192 is_powered_on = true; 196 is_powered_on = true;
193 exit_lock = false; 197 exit_lock = false;
194 198
@@ -387,6 +391,7 @@ struct System::Impl {
387 /// Service State 391 /// Service State
388 Service::Glue::ARPManager arp_manager; 392 Service::Glue::ARPManager arp_manager;
389 Service::LM::Manager lm_manager{reporter}; 393 Service::LM::Manager lm_manager{reporter};
394 Service::Time::TimeManager time_manager;
390 395
391 /// Service manager 396 /// Service manager
392 std::shared_ptr<Service::SM::ServiceManager> service_manager; 397 std::shared_ptr<Service::SM::ServiceManager> service_manager;
@@ -717,6 +722,14 @@ const Service::LM::Manager& System::GetLogManager() const {
717 return impl->lm_manager; 722 return impl->lm_manager;
718} 723}
719 724
725Service::Time::TimeManager& System::GetTimeManager() {
726 return impl->time_manager;
727}
728
729const Service::Time::TimeManager& System::GetTimeManager() const {
730 return impl->time_manager;
731}
732
720void System::SetExitLock(bool locked) { 733void System::SetExitLock(bool locked) {
721 impl->exit_lock = locked; 734 impl->exit_lock = locked;
722} 735}
diff --git a/src/core/core.h b/src/core/core.h
index 27efe30bb..6db896bae 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -69,6 +69,10 @@ namespace SM {
69class ServiceManager; 69class ServiceManager;
70} // namespace SM 70} // namespace SM
71 71
72namespace Time {
73class TimeManager;
74} // namespace Time
75
72} // namespace Service 76} // namespace Service
73 77
74namespace Tegra { 78namespace Tegra {
@@ -361,6 +365,10 @@ public:
361 365
362 const Service::LM::Manager& GetLogManager() const; 366 const Service::LM::Manager& GetLogManager() const;
363 367
368 Service::Time::TimeManager& GetTimeManager();
369
370 const Service::Time::TimeManager& GetTimeManager() const;
371
364 void SetExitLock(bool locked); 372 void SetExitLock(bool locked);
365 373
366 bool GetExitLock() const; 374 bool GetExitLock() const;
diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp
index ee4fa4b48..7d0474e0b 100644
--- a/src/core/hle/service/time/time.cpp
+++ b/src/core/hle/service/time/time.cpp
@@ -10,6 +10,7 @@
10#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
11#include "core/hle/kernel/client_port.h" 11#include "core/hle/kernel/client_port.h"
12#include "core/hle/kernel/client_session.h" 12#include "core/hle/kernel/client_session.h"
13#include "core/hle/kernel/kernel.h"
13#include "core/hle/kernel/scheduler.h" 14#include "core/hle/kernel/scheduler.h"
14#include "core/hle/service/time/interface.h" 15#include "core/hle/service/time/interface.h"
15#include "core/hle/service/time/time.h" 16#include "core/hle/service/time/time.h"
@@ -125,7 +126,7 @@ ResultCode Module::Interface::GetClockSnapshotFromSystemClockContextInternal(
125 Kernel::Thread* thread, Clock::SystemClockContext user_context, 126 Kernel::Thread* thread, Clock::SystemClockContext user_context,
126 Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) { 127 Clock::SystemClockContext network_context, u8 type, Clock::ClockSnapshot& clock_snapshot) {
127 128
128 auto& time_manager{module->GetTimeManager()}; 129 auto& time_manager{system.GetTimeManager()};
129 130
130 clock_snapshot.is_automatic_correction_enabled = 131 clock_snapshot.is_automatic_correction_enabled =
131 time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled(); 132 time_manager.GetStandardUserSystemClockCore().IsAutomaticCorrectionEnabled();
@@ -182,7 +183,7 @@ void Module::Interface::GetStandardUserSystemClock(Kernel::HLERequestContext& ct
182 LOG_DEBUG(Service_Time, "called"); 183 LOG_DEBUG(Service_Time, "called");
183 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 184 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
184 rb.Push(RESULT_SUCCESS); 185 rb.Push(RESULT_SUCCESS);
185 rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardUserSystemClockCore(), 186 rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardUserSystemClockCore(),
186 system); 187 system);
187} 188}
188 189
@@ -190,7 +191,7 @@ void Module::Interface::GetStandardNetworkSystemClock(Kernel::HLERequestContext&
190 LOG_DEBUG(Service_Time, "called"); 191 LOG_DEBUG(Service_Time, "called");
191 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 192 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
192 rb.Push(RESULT_SUCCESS); 193 rb.Push(RESULT_SUCCESS);
193 rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardNetworkSystemClockCore(), 194 rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardNetworkSystemClockCore(),
194 system); 195 system);
195} 196}
196 197
@@ -198,29 +199,28 @@ void Module::Interface::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
198 LOG_DEBUG(Service_Time, "called"); 199 LOG_DEBUG(Service_Time, "called");
199 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 200 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
200 rb.Push(RESULT_SUCCESS); 201 rb.Push(RESULT_SUCCESS);
201 rb.PushIpcInterface<ISteadyClock>(module->GetTimeManager().GetStandardSteadyClockCore(), 202 rb.PushIpcInterface<ISteadyClock>(system.GetTimeManager().GetStandardSteadyClockCore(), system);
202 system);
203} 203}
204 204
205void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) { 205void Module::Interface::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
206 LOG_DEBUG(Service_Time, "called"); 206 LOG_DEBUG(Service_Time, "called");
207 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 207 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
208 rb.Push(RESULT_SUCCESS); 208 rb.Push(RESULT_SUCCESS);
209 rb.PushIpcInterface<ITimeZoneService>(module->GetTimeManager().GetTimeZoneContentManager()); 209 rb.PushIpcInterface<ITimeZoneService>(system.GetTimeManager().GetTimeZoneContentManager());
210} 210}
211 211
212void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) { 212void Module::Interface::GetStandardLocalSystemClock(Kernel::HLERequestContext& ctx) {
213 LOG_DEBUG(Service_Time, "called"); 213 LOG_DEBUG(Service_Time, "called");
214 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 214 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
215 rb.Push(RESULT_SUCCESS); 215 rb.Push(RESULT_SUCCESS);
216 rb.PushIpcInterface<ISystemClock>(module->GetTimeManager().GetStandardLocalSystemClockCore(), 216 rb.PushIpcInterface<ISystemClock>(system.GetTimeManager().GetStandardLocalSystemClockCore(),
217 system); 217 system);
218} 218}
219 219
220void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient( 220void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(
221 Kernel::HLERequestContext& ctx) { 221 Kernel::HLERequestContext& ctx) {
222 LOG_DEBUG(Service_Time, "called"); 222 LOG_DEBUG(Service_Time, "called");
223 auto& clock_core{module->GetTimeManager().GetStandardNetworkSystemClockCore()}; 223 auto& clock_core{system.GetTimeManager().GetStandardNetworkSystemClockCore()};
224 IPC::ResponseBuilder rb{ctx, 3}; 224 IPC::ResponseBuilder rb{ctx, 3};
225 rb.Push(RESULT_SUCCESS); 225 rb.Push(RESULT_SUCCESS);
226 rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system)); 226 rb.Push<u32>(clock_core.IsStandardNetworkSystemClockAccuracySufficient(system));
@@ -229,7 +229,7 @@ void Module::Interface::IsStandardNetworkSystemClockAccuracySufficient(
229void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) { 229void Module::Interface::CalculateMonotonicSystemClockBaseTimePoint(Kernel::HLERequestContext& ctx) {
230 LOG_DEBUG(Service_Time, "called"); 230 LOG_DEBUG(Service_Time, "called");
231 231
232 auto& steady_clock_core{module->GetTimeManager().GetStandardSteadyClockCore()}; 232 auto& steady_clock_core{system.GetTimeManager().GetStandardSteadyClockCore()};
233 if (!steady_clock_core.IsInitialized()) { 233 if (!steady_clock_core.IsInitialized()) {
234 IPC::ResponseBuilder rb{ctx, 2}; 234 IPC::ResponseBuilder rb{ctx, 2};
235 rb.Push(ERROR_UNINITIALIZED_CLOCK); 235 rb.Push(ERROR_UNINITIALIZED_CLOCK);
@@ -262,8 +262,8 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
262 262
263 Clock::SystemClockContext user_context{}; 263 Clock::SystemClockContext user_context{};
264 if (const ResultCode result{ 264 if (const ResultCode result{
265 module->GetTimeManager().GetStandardUserSystemClockCore().GetClockContext( 265 system.GetTimeManager().GetStandardUserSystemClockCore().GetClockContext(system,
266 system, user_context)}; 266 user_context)};
267 result.IsError()) { 267 result.IsError()) {
268 IPC::ResponseBuilder rb{ctx, 2}; 268 IPC::ResponseBuilder rb{ctx, 2};
269 rb.Push(result); 269 rb.Push(result);
@@ -271,7 +271,7 @@ void Module::Interface::GetClockSnapshot(Kernel::HLERequestContext& ctx) {
271 } 271 }
272 Clock::SystemClockContext network_context{}; 272 Clock::SystemClockContext network_context{};
273 if (const ResultCode result{ 273 if (const ResultCode result{
274 module->GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext( 274 system.GetTimeManager().GetStandardNetworkSystemClockCore().GetClockContext(
275 system, network_context)}; 275 system, network_context)};
276 result.IsError()) { 276 result.IsError()) {
277 IPC::ResponseBuilder rb{ctx, 2}; 277 IPC::ResponseBuilder rb{ctx, 2};
@@ -372,7 +372,7 @@ void Module::Interface::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& c
372 LOG_DEBUG(Service_Time, "called"); 372 LOG_DEBUG(Service_Time, "called");
373 IPC::ResponseBuilder rb{ctx, 2, 1}; 373 IPC::ResponseBuilder rb{ctx, 2, 1};
374 rb.Push(RESULT_SUCCESS); 374 rb.Push(RESULT_SUCCESS);
375 rb.PushCopyObjects(module->GetTimeManager().GetSharedMemory().GetSharedMemoryHolder()); 375 rb.PushCopyObjects(SharedFrom(&system.Kernel().GetTimeSharedMem()));
376} 376}
377 377
378Module::Interface::Interface(std::shared_ptr<Module> module, Core::System& system, const char* name) 378Module::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
381Module::Interface::~Interface() = default; 381Module::Interface::~Interface() = default;
382 382
383void InstallInterfaces(Core::System& system) { 383void InstallInterfaces(Core::System& system) {
384 auto module{std::make_shared<Module>(system)}; 384 auto module{std::make_shared<Module>()};
385 std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager()); 385 std::make_shared<Time>(module, system, "time:a")->InstallAsService(system.ServiceManager());
386 std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager()); 386 std::make_shared<Time>(module, system, "time:s")->InstallAsService(system.ServiceManager());
387 std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager()); 387 std::make_shared<Time>(module, system, "time:u")->InstallAsService(system.ServiceManager());
diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h
index 41f3002e9..49f4aac0a 100644
--- a/src/core/hle/service/time/time.h
+++ b/src/core/hle/service/time/time.h
@@ -16,7 +16,7 @@ namespace Service::Time {
16 16
17class Module final { 17class Module final {
18public: 18public:
19 Module(Core::System& system) : time_manager{system} {} 19 Module() = default;
20 20
21 class Interface : public ServiceFramework<Interface> { 21 class Interface : public ServiceFramework<Interface> {
22 public: 22 public:
@@ -46,13 +46,6 @@ public:
46 std::shared_ptr<Module> module; 46 std::shared_ptr<Module> module;
47 Core::System& system; 47 Core::System& system;
48 }; 48 };
49
50 TimeManager& GetTimeManager() {
51 return time_manager;
52 }
53
54private:
55 TimeManager time_manager;
56}; 49};
57 50
58/// Registers all Time services with the specified service manager. 51/// Registers all Time services with the specified service manager.
diff --git a/src/core/hle/service/time/time_manager.cpp b/src/core/hle/service/time/time_manager.cpp
index b4dfe45e5..858623e2b 100644
--- a/src/core/hle/service/time/time_manager.cpp
+++ b/src/core/hle/service/time/time_manager.cpp
@@ -22,125 +22,282 @@ static std::chrono::seconds GetSecondsSinceEpoch() {
22 Settings::values.custom_rtc_differential; 22 Settings::values.custom_rtc_differential;
23} 23}
24 24
25static s64 GetExternalTimeZoneOffset() {
26 // With "auto" timezone setting, we use the external system's timezone offset
27 if (Settings::GetTimeZoneString() == "auto") {
28 return Common::TimeZone::GetCurrentOffsetSeconds().count();
29 }
30 return 0;
31}
32
33static s64 GetExternalRtcValue() { 25static s64 GetExternalRtcValue() {
34 return GetSecondsSinceEpoch().count() + GetExternalTimeZoneOffset(); 26 return GetSecondsSinceEpoch().count() + TimeManager::GetExternalTimeZoneOffset();
35}
36
37TimeManager::TimeManager(Core::System& system)
38 : shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core},
39 standard_network_system_clock_core{standard_steady_clock_core},
40 standard_user_system_clock_core{standard_local_system_clock_core,
41 standard_network_system_clock_core, system},
42 ephemeral_network_system_clock_core{tick_based_steady_clock_core},
43 local_system_clock_context_writer{
44 std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)},
45 network_system_clock_context_writer{
46 std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)},
47 ephemeral_network_system_clock_context_writer{
48 std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
49 time_zone_content_manager{*this, system} {
50
51 const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
52 SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {});
53 SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
54 SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy);
55 SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
56 SetupEphemeralNetworkSystemClock();
57} 27}
58 28
59TimeManager::~TimeManager() = default; 29struct TimeManager::Impl final {
30 explicit Impl(Core::System& system)
31 : shared_memory{system}, standard_local_system_clock_core{standard_steady_clock_core},
32 standard_network_system_clock_core{standard_steady_clock_core},
33 standard_user_system_clock_core{standard_local_system_clock_core,
34 standard_network_system_clock_core, system},
35 ephemeral_network_system_clock_core{tick_based_steady_clock_core},
36 local_system_clock_context_writer{
37 std::make_shared<Clock::LocalSystemClockContextWriter>(shared_memory)},
38 network_system_clock_context_writer{
39 std::make_shared<Clock::NetworkSystemClockContextWriter>(shared_memory)},
40 ephemeral_network_system_clock_context_writer{
41 std::make_shared<Clock::EphemeralNetworkSystemClockContextWriter>()},
42 time_zone_content_manager{system} {
60 43
61void TimeManager::SetupTimeZoneManager(std::string location_name, 44 const auto system_time{Clock::TimeSpanType::FromSeconds(GetExternalRtcValue())};
62 Clock::SteadyClockTimePoint time_zone_updated_time_point, 45 SetupStandardSteadyClock(system, Common::UUID::Generate(), system_time, {}, {});
63 std::size_t total_location_name_count, 46 SetupStandardLocalSystemClock(system, {}, system_time.ToSeconds());
64 u128 time_zone_rule_version, 47 SetupStandardNetworkSystemClock({}, standard_network_clock_accuracy);
65 FileSys::VirtualFile& vfs_file) { 48 SetupStandardUserSystemClock(system, {}, Clock::SteadyClockTimePoint::GetRandom());
66 if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule( 49 SetupEphemeralNetworkSystemClock();
67 location_name, vfs_file) != RESULT_SUCCESS) { 50 }
68 UNREACHABLE(); 51
69 return; 52 ~Impl() = default;
70 } 53
71 54 Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() {
72 time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point); 55 return standard_steady_clock_core;
73 time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount( 56 }
74 total_location_name_count); 57
75 time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(time_zone_rule_version); 58 const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const {
76 time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized(); 59 return standard_steady_clock_core;
77} 60 }
78 61
79void TimeManager::SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, 62 Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() {
80 Clock::TimeSpanType setup_value, 63 return standard_local_system_clock_core;
81 Clock::TimeSpanType internal_offset, 64 }
82 bool is_rtc_reset_detected) { 65
83 standard_steady_clock_core.SetClockSourceId(clock_source_id); 66 const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const {
84 standard_steady_clock_core.SetSetupValue(setup_value); 67 return standard_local_system_clock_core;
85 standard_steady_clock_core.SetInternalOffset(internal_offset); 68 }
86 standard_steady_clock_core.MarkAsInitialized(); 69
87 70 Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() {
88 const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)}; 71 return standard_network_system_clock_core;
89 shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point); 72 }
90} 73
91 74 const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const {
92void TimeManager::SetupStandardLocalSystemClock(Core::System& system, 75 return standard_network_system_clock_core;
93 Clock::SystemClockContext clock_context, 76 }
94 s64 posix_time) { 77
95 standard_local_system_clock_core.SetUpdateCallbackInstance(local_system_clock_context_writer); 78 Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() {
96 79 return standard_user_system_clock_core;
97 const auto current_time_point{ 80 }
98 standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)}; 81
99 if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) { 82 const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const {
100 standard_local_system_clock_core.SetSystemClockContext(clock_context); 83 return standard_user_system_clock_core;
101 } else { 84 }
102 if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) != RESULT_SUCCESS) { 85
86 TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() {
87 return time_zone_content_manager;
88 }
89
90 const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const {
91 return time_zone_content_manager;
92 }
93
94 SharedMemory& GetSharedMemory() {
95 return shared_memory;
96 }
97
98 const SharedMemory& GetSharedMemory() const {
99 return shared_memory;
100 }
101
102 void SetupTimeZoneManager(std::string location_name,
103 Clock::SteadyClockTimePoint time_zone_updated_time_point,
104 std::size_t total_location_name_count, u128 time_zone_rule_version,
105 FileSys::VirtualFile& vfs_file) {
106 if (time_zone_content_manager.GetTimeZoneManager().SetDeviceLocationNameWithTimeZoneRule(
107 location_name, vfs_file) != RESULT_SUCCESS) {
103 UNREACHABLE(); 108 UNREACHABLE();
104 return; 109 return;
105 } 110 }
111
112 time_zone_content_manager.GetTimeZoneManager().SetUpdatedTime(time_zone_updated_time_point);
113 time_zone_content_manager.GetTimeZoneManager().SetTotalLocationNameCount(
114 total_location_name_count);
115 time_zone_content_manager.GetTimeZoneManager().SetTimeZoneRuleVersion(
116 time_zone_rule_version);
117 time_zone_content_manager.GetTimeZoneManager().MarkAsInitialized();
106 } 118 }
107 119
108 standard_local_system_clock_core.MarkAsInitialized(); 120 static s64 GetExternalTimeZoneOffset() {
109} 121 // With "auto" timezone setting, we use the external system's timezone offset
122 if (Settings::GetTimeZoneString() == "auto") {
123 return Common::TimeZone::GetCurrentOffsetSeconds().count();
124 }
125 return 0;
126 }
110 127
111void TimeManager::SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context, 128 void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id,
112 Clock::TimeSpanType sufficient_accuracy) { 129 Clock::TimeSpanType setup_value,
113 standard_network_system_clock_core.SetUpdateCallbackInstance( 130 Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected) {
114 network_system_clock_context_writer); 131 standard_steady_clock_core.SetClockSourceId(clock_source_id);
132 standard_steady_clock_core.SetSetupValue(setup_value);
133 standard_steady_clock_core.SetInternalOffset(internal_offset);
134 standard_steady_clock_core.MarkAsInitialized();
115 135
116 if (standard_network_system_clock_core.SetSystemClockContext(clock_context) != RESULT_SUCCESS) { 136 const auto current_time_point{standard_steady_clock_core.GetCurrentRawTimePoint(system)};
117 UNREACHABLE(); 137 shared_memory.SetupStandardSteadyClock(system, clock_source_id, current_time_point);
118 return;
119 } 138 }
120 139
121 standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy( 140 void SetupStandardLocalSystemClock(Core::System& system,
122 sufficient_accuracy); 141 Clock::SystemClockContext clock_context, s64 posix_time) {
123 standard_network_system_clock_core.MarkAsInitialized(); 142 standard_local_system_clock_core.SetUpdateCallbackInstance(
124} 143 local_system_clock_context_writer);
144
145 const auto current_time_point{
146 standard_local_system_clock_core.GetSteadyClockCore().GetCurrentTimePoint(system)};
147 if (current_time_point.clock_source_id == clock_context.steady_time_point.clock_source_id) {
148 standard_local_system_clock_core.SetSystemClockContext(clock_context);
149 } else {
150 if (standard_local_system_clock_core.SetCurrentTime(system, posix_time) !=
151 RESULT_SUCCESS) {
152 UNREACHABLE();
153 return;
154 }
155 }
156
157 standard_local_system_clock_core.MarkAsInitialized();
158 }
159
160 void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
161 Clock::TimeSpanType sufficient_accuracy) {
162 standard_network_system_clock_core.SetUpdateCallbackInstance(
163 network_system_clock_context_writer);
125 164
126void TimeManager::SetupStandardUserSystemClock( 165 if (standard_network_system_clock_core.SetSystemClockContext(clock_context) !=
127 Core::System& system, bool is_automatic_correction_enabled, 166 RESULT_SUCCESS) {
128 Clock::SteadyClockTimePoint steady_clock_time_point) { 167 UNREACHABLE();
129 if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled( 168 return;
130 system, is_automatic_correction_enabled) != RESULT_SUCCESS) { 169 }
131 UNREACHABLE(); 170
132 return; 171 standard_network_system_clock_core.SetStandardNetworkClockSufficientAccuracy(
172 sufficient_accuracy);
173 standard_network_system_clock_core.MarkAsInitialized();
133 } 174 }
134 175
135 standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point); 176 void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled,
136 standard_user_system_clock_core.MarkAsInitialized(); 177 Clock::SteadyClockTimePoint steady_clock_time_point) {
137 shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled); 178 if (standard_user_system_clock_core.SetAutomaticCorrectionEnabled(
179 system, is_automatic_correction_enabled) != RESULT_SUCCESS) {
180 UNREACHABLE();
181 return;
182 }
183
184 standard_user_system_clock_core.SetAutomaticCorrectionUpdatedTime(steady_clock_time_point);
185 standard_user_system_clock_core.MarkAsInitialized();
186 shared_memory.SetAutomaticCorrectionEnabled(is_automatic_correction_enabled);
187 }
188
189 void SetupEphemeralNetworkSystemClock() {
190 ephemeral_network_system_clock_core.SetUpdateCallbackInstance(
191 ephemeral_network_system_clock_context_writer);
192 ephemeral_network_system_clock_core.MarkAsInitialized();
193 }
194
195 void UpdateLocalSystemClockTime(Core::System& system, s64 posix_time) {
196 const auto timespan{Service::Time::Clock::TimeSpanType::FromSeconds(posix_time)};
197 if (GetStandardLocalSystemClockCore()
198 .SetCurrentTime(system, timespan.ToSeconds())
199 .IsError()) {
200 UNREACHABLE();
201 return;
202 }
203 }
204
205 SharedMemory shared_memory;
206
207 Clock::StandardSteadyClockCore standard_steady_clock_core;
208 Clock::TickBasedSteadyClockCore tick_based_steady_clock_core;
209 Clock::StandardLocalSystemClockCore standard_local_system_clock_core;
210 Clock::StandardNetworkSystemClockCore standard_network_system_clock_core;
211 Clock::StandardUserSystemClockCore standard_user_system_clock_core;
212 Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core;
213
214 std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer;
215 std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer;
216 std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter>
217 ephemeral_network_system_clock_context_writer;
218
219 TimeZone::TimeZoneContentManager time_zone_content_manager;
220};
221
222TimeManager::TimeManager(Core::System& system) : system{system} {}
223
224TimeManager::~TimeManager() = default;
225
226void TimeManager::Initialize() {
227 impl = std::make_unique<Impl>(system);
228
229 // Time zones can only be initialized after impl is valid
230 impl->time_zone_content_manager.Initialize(*this);
231}
232
233Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() {
234 return impl->standard_steady_clock_core;
235}
236
237const Clock::StandardSteadyClockCore& TimeManager::GetStandardSteadyClockCore() const {
238 return impl->standard_steady_clock_core;
239}
240
241Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() {
242 return impl->standard_local_system_clock_core;
243}
244
245const Clock::StandardLocalSystemClockCore& TimeManager::GetStandardLocalSystemClockCore() const {
246 return impl->standard_local_system_clock_core;
247}
248
249Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore() {
250 return impl->standard_network_system_clock_core;
138} 251}
139 252
140void TimeManager::SetupEphemeralNetworkSystemClock() { 253const Clock::StandardNetworkSystemClockCore& TimeManager::GetStandardNetworkSystemClockCore()
141 ephemeral_network_system_clock_core.SetUpdateCallbackInstance( 254 const {
142 ephemeral_network_system_clock_context_writer); 255 return impl->standard_network_system_clock_core;
143 ephemeral_network_system_clock_core.MarkAsInitialized(); 256}
257
258Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() {
259 return impl->standard_user_system_clock_core;
260}
261
262const Clock::StandardUserSystemClockCore& TimeManager::GetStandardUserSystemClockCore() const {
263 return impl->standard_user_system_clock_core;
264}
265
266TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() {
267 return impl->time_zone_content_manager;
268}
269
270const TimeZone::TimeZoneContentManager& TimeManager::GetTimeZoneContentManager() const {
271 return impl->time_zone_content_manager;
272}
273
274SharedMemory& TimeManager::GetSharedMemory() {
275 return impl->shared_memory;
276}
277
278const SharedMemory& TimeManager::GetSharedMemory() const {
279 return impl->shared_memory;
280}
281
282void TimeManager::UpdateLocalSystemClockTime(s64 posix_time) {
283 impl->UpdateLocalSystemClockTime(system, posix_time);
284}
285
286void TimeManager::SetupTimeZoneManager(std::string location_name,
287 Clock::SteadyClockTimePoint time_zone_updated_time_point,
288 std::size_t total_location_name_count,
289 u128 time_zone_rule_version,
290 FileSys::VirtualFile& vfs_file) {
291 impl->SetupTimeZoneManager(location_name, time_zone_updated_time_point,
292 total_location_name_count, time_zone_rule_version, vfs_file);
293}
294
295/*static*/ s64 TimeManager::GetExternalTimeZoneOffset() {
296 // With "auto" timezone setting, we use the external system's timezone offset
297 if (Settings::GetTimeZoneString() == "auto") {
298 return Common::TimeZone::GetCurrentOffsetSeconds().count();
299 }
300 return 0;
144} 301}
145 302
146} // namespace Service::Time 303} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_manager.h b/src/core/hle/service/time/time_manager.h
index 8e65f0d22..993c7c288 100644
--- a/src/core/hle/service/time/time_manager.h
+++ b/src/core/hle/service/time/time_manager.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/time_zone.h"
8#include "core/file_sys/vfs_types.h" 9#include "core/file_sys/vfs_types.h"
9#include "core/hle/service/time/clock_types.h" 10#include "core/hle/service/time/clock_types.h"
10#include "core/hle/service/time/ephemeral_network_system_clock_core.h" 11#include "core/hle/service/time/ephemeral_network_system_clock_core.h"
@@ -32,86 +33,46 @@ public:
32 explicit TimeManager(Core::System& system); 33 explicit TimeManager(Core::System& system);
33 ~TimeManager(); 34 ~TimeManager();
34 35
35 Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() { 36 void Initialize();
36 return standard_steady_clock_core;
37 }
38 37
39 const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const { 38 Clock::StandardSteadyClockCore& GetStandardSteadyClockCore();
40 return standard_steady_clock_core;
41 }
42 39
43 Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() { 40 const Clock::StandardSteadyClockCore& GetStandardSteadyClockCore() const;
44 return standard_local_system_clock_core;
45 }
46 41
47 const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const { 42 Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore();
48 return standard_local_system_clock_core;
49 }
50 43
51 Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() { 44 const Clock::StandardLocalSystemClockCore& GetStandardLocalSystemClockCore() const;
52 return standard_network_system_clock_core;
53 }
54 45
55 const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const { 46 Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore();
56 return standard_network_system_clock_core;
57 }
58 47
59 Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() { 48 const Clock::StandardNetworkSystemClockCore& GetStandardNetworkSystemClockCore() const;
60 return standard_user_system_clock_core;
61 }
62 49
63 const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const { 50 Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore();
64 return standard_user_system_clock_core;
65 }
66 51
67 TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() { 52 const Clock::StandardUserSystemClockCore& GetStandardUserSystemClockCore() const;
68 return time_zone_content_manager;
69 }
70 53
71 const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const { 54 TimeZone::TimeZoneContentManager& GetTimeZoneContentManager();
72 return time_zone_content_manager;
73 }
74 55
75 SharedMemory& GetSharedMemory() { 56 const TimeZone::TimeZoneContentManager& GetTimeZoneContentManager() const;
76 return shared_memory;
77 }
78 57
79 const SharedMemory& GetSharedMemory() const { 58 void UpdateLocalSystemClockTime(s64 posix_time);
80 return shared_memory; 59
81 } 60 SharedMemory& GetSharedMemory();
61
62 const SharedMemory& GetSharedMemory() const;
82 63
83 void SetupTimeZoneManager(std::string location_name, 64 void SetupTimeZoneManager(std::string location_name,
84 Clock::SteadyClockTimePoint time_zone_updated_time_point, 65 Clock::SteadyClockTimePoint time_zone_updated_time_point,
85 std::size_t total_location_name_count, u128 time_zone_rule_version, 66 std::size_t total_location_name_count, u128 time_zone_rule_version,
86 FileSys::VirtualFile& vfs_file); 67 FileSys::VirtualFile& vfs_file);
87 68
69 static s64 GetExternalTimeZoneOffset();
70
88private: 71private:
89 void SetupStandardSteadyClock(Core::System& system, Common::UUID clock_source_id, 72 Core::System& system;
90 Clock::TimeSpanType setup_value, 73
91 Clock::TimeSpanType internal_offset, bool is_rtc_reset_detected); 74 struct Impl;
92 void SetupStandardLocalSystemClock(Core::System& system, 75 std::unique_ptr<Impl> impl;
93 Clock::SystemClockContext clock_context, s64 posix_time);
94 void SetupStandardNetworkSystemClock(Clock::SystemClockContext clock_context,
95 Clock::TimeSpanType sufficient_accuracy);
96 void SetupStandardUserSystemClock(Core::System& system, bool is_automatic_correction_enabled,
97 Clock::SteadyClockTimePoint steady_clock_time_point);
98 void SetupEphemeralNetworkSystemClock();
99
100 SharedMemory shared_memory;
101
102 Clock::StandardSteadyClockCore standard_steady_clock_core;
103 Clock::TickBasedSteadyClockCore tick_based_steady_clock_core;
104 Clock::StandardLocalSystemClockCore standard_local_system_clock_core;
105 Clock::StandardNetworkSystemClockCore standard_network_system_clock_core;
106 Clock::StandardUserSystemClockCore standard_user_system_clock_core;
107 Clock::EphemeralNetworkSystemClockCore ephemeral_network_system_clock_core;
108
109 std::shared_ptr<Clock::LocalSystemClockContextWriter> local_system_clock_context_writer;
110 std::shared_ptr<Clock::NetworkSystemClockContextWriter> network_system_clock_context_writer;
111 std::shared_ptr<Clock::EphemeralNetworkSystemClockContextWriter>
112 ephemeral_network_system_clock_context_writer;
113
114 TimeZone::TimeZoneContentManager time_zone_content_manager;
115}; 76};
116 77
117} // namespace Service::Time 78} // namespace Service::Time
diff --git a/src/core/hle/service/time/time_zone_content_manager.cpp b/src/core/hle/service/time/time_zone_content_manager.cpp
index 320672add..4177d0a41 100644
--- a/src/core/hle/service/time/time_zone_content_manager.cpp
+++ b/src/core/hle/service/time/time_zone_content_manager.cpp
@@ -68,9 +68,10 @@ static std::vector<std::string> BuildLocationNameCache(Core::System& system) {
68 return location_name_cache; 68 return location_name_cache;
69} 69}
70 70
71TimeZoneContentManager::TimeZoneContentManager(TimeManager& time_manager, Core::System& system) 71TimeZoneContentManager::TimeZoneContentManager(Core::System& system)
72 : system{system}, location_name_cache{BuildLocationNameCache(system)} { 72 : system{system}, location_name_cache{BuildLocationNameCache(system)} {}
73 73
74void TimeZoneContentManager::Initialize(TimeManager& time_manager) {
74 std::string location_name; 75 std::string location_name;
75 const auto timezone_setting = Settings::GetTimeZoneString(); 76 const auto timezone_setting = Settings::GetTimeZoneString();
76 if (timezone_setting == "auto" || timezone_setting == "default") { 77 if (timezone_setting == "auto" || timezone_setting == "default") {
diff --git a/src/core/hle/service/time/time_zone_content_manager.h b/src/core/hle/service/time/time_zone_content_manager.h
index 4f302c3b9..02bbbadac 100644
--- a/src/core/hle/service/time/time_zone_content_manager.h
+++ b/src/core/hle/service/time/time_zone_content_manager.h
@@ -21,7 +21,9 @@ namespace Service::Time::TimeZone {
21 21
22class TimeZoneContentManager final { 22class TimeZoneContentManager final {
23public: 23public:
24 TimeZoneContentManager(TimeManager& time_manager, Core::System& system); 24 TimeZoneContentManager(Core::System& system);
25
26 void Initialize(TimeManager& time_manager);
25 27
26 TimeZoneManager& GetTimeZoneManager() { 28 TimeZoneManager& GetTimeZoneManager() {
27 return time_zone_manager; 29 return time_zone_manager;
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp
index 9ad43ed8f..5e8e201dc 100644
--- a/src/yuzu/configuration/configure_system.cpp
+++ b/src/yuzu/configuration/configure_system.cpp
@@ -12,6 +12,7 @@
12#include "common/assert.h" 12#include "common/assert.h"
13#include "common/file_util.h" 13#include "common/file_util.h"
14#include "core/core.h" 14#include "core/core.h"
15#include "core/hle/service/time/time.h"
15#include "core/settings.h" 16#include "core/settings.h"
16#include "ui_configure_system.h" 17#include "ui_configure_system.h"
17#include "yuzu/configuration/configuration_shared.h" 18#include "yuzu/configuration/configuration_shared.h"
@@ -104,6 +105,22 @@ void ConfigureSystem::SetConfiguration() {
104void ConfigureSystem::ReadSystemSettings() {} 105void ConfigureSystem::ReadSystemSettings() {}
105 106
106void ConfigureSystem::ApplyConfiguration() { 107void ConfigureSystem::ApplyConfiguration() {
108 // Allow setting custom RTC even if system is powered on, to allow in-game time to be fast
109 // forwared
110 if (Settings::values.custom_rtc.UsingGlobal()) {
111 if (ui->custom_rtc_checkbox->isChecked()) {
112 Settings::values.custom_rtc.SetValue(
113 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
114 if (Core::System::GetInstance().IsPoweredOn()) {
115 const s64 posix_time{Settings::values.custom_rtc.GetValue()->count() +
116 Service::Time::TimeManager::GetExternalTimeZoneOffset()};
117 Core::System::GetInstance().GetTimeManager().UpdateLocalSystemClockTime(posix_time);
118 }
119 } else {
120 Settings::values.custom_rtc.SetValue(std::nullopt);
121 }
122 }
123
107 if (!enabled) { 124 if (!enabled) {
108 return; 125 return;
109 } 126 }
@@ -131,15 +148,6 @@ void ConfigureSystem::ApplyConfiguration() {
131 Settings::values.rng_seed.SetValue(std::nullopt); 148 Settings::values.rng_seed.SetValue(std::nullopt);
132 } 149 }
133 } 150 }
134
135 if (Settings::values.custom_rtc.UsingGlobal()) {
136 if (ui->custom_rtc_checkbox->isChecked()) {
137 Settings::values.custom_rtc.SetValue(
138 std::chrono::seconds(ui->custom_rtc_edit->dateTime().toSecsSinceEpoch()));
139 } else {
140 Settings::values.custom_rtc.SetValue(std::nullopt);
141 }
142 }
143 } else { 151 } else {
144 ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index, 152 ConfigurationShared::ApplyPerGameSetting(&Settings::values.language_index,
145 ui->combo_language); 153 ui->combo_language);