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);
|
||||
|
|
Reference in New Issue