Move every clocks instances + timezone to a global manager
This commit is contained in:
parent
26b4aad831
commit
eb02cfa777
12 changed files with 105 additions and 146 deletions
|
@ -1,6 +1,6 @@
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
using LibHac.Fs.NcaUtils;
|
using LibHac.Fs.NcaUtils;
|
||||||
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
using Ryujinx.HLE.HOS.Services.Time;
|
||||||
using Ryujinx.HLE.Utilities;
|
using Ryujinx.HLE.Utilities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -143,7 +143,7 @@ namespace Ryujinx.HLE.FileSystem.Content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TimeZoneManager.Instance.Initialize(_device);
|
TimeManager.Instance.TimeZone.Initialize(_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearEntry(long titleId, ContentType contentType, StorageId storageId)
|
public void ClearEntry(long titleId, ContentType contentType, StorageId storageId)
|
||||||
|
|
|
@ -22,6 +22,8 @@ using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
|
using TimeServiceManager = Ryujinx.HLE.HOS.Services.Time.TimeManager;
|
||||||
|
|
||||||
using NxStaticObject = Ryujinx.HLE.Loaders.Executables.NxStaticObject;
|
using NxStaticObject = Ryujinx.HLE.Loaders.Executables.NxStaticObject;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS
|
namespace Ryujinx.HLE.HOS
|
||||||
|
@ -202,13 +204,15 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
// TODO: use set:sys (and set external clock source id from settings)
|
// TODO: use set:sys (and set external clock source id from settings)
|
||||||
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
|
// TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate.
|
||||||
StandardSteadyClockCore.Instance.ConfigureSetupValue();
|
// TODO: migrate to 9.0.0+
|
||||||
|
TimeServiceManager.Instance.StandardSteadyClock.ConfigureSetupValue();
|
||||||
|
TimeServiceManager.Instance.StandardSteadyClock.MarkInitialized();
|
||||||
|
|
||||||
if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
|
if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes))
|
||||||
{
|
{
|
||||||
TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000);
|
TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000);
|
||||||
|
|
||||||
StandardNetworkSystemClockCore.Instance.SetStandardNetworkClockSufficientAccuracy(standardNetworkClockSufficientAccuracy);
|
TimeServiceManager.Instance.StandardNetworkSystemClock.SetStandardNetworkClockSufficientAccuracy(standardNetworkClockSufficientAccuracy);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,21 +2,6 @@
|
||||||
{
|
{
|
||||||
class EphemeralNetworkSystemClockCore : SystemClockCore
|
class EphemeralNetworkSystemClockCore : SystemClockCore
|
||||||
{
|
{
|
||||||
private static EphemeralNetworkSystemClockCore _instance;
|
|
||||||
|
|
||||||
public static EphemeralNetworkSystemClockCore Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
_instance = new EphemeralNetworkSystemClockCore(TickBasedSteadyClockCore.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
|
public EphemeralNetworkSystemClockCore(SteadyClockCore steadyClockCore) : base(steadyClockCore) { }
|
||||||
|
|
||||||
protected override ResultCode Flush(SystemClockContext context)
|
protected override ResultCode Flush(SystemClockContext context)
|
||||||
|
|
|
@ -2,21 +2,6 @@
|
||||||
{
|
{
|
||||||
class StandardLocalSystemClockCore : SystemClockCore
|
class StandardLocalSystemClockCore : SystemClockCore
|
||||||
{
|
{
|
||||||
private static StandardLocalSystemClockCore _instance;
|
|
||||||
|
|
||||||
public static StandardLocalSystemClockCore Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
_instance = new StandardLocalSystemClockCore(StandardSteadyClockCore.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {}
|
public StandardLocalSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore) {}
|
||||||
|
|
||||||
protected override ResultCode Flush(SystemClockContext context)
|
protected override ResultCode Flush(SystemClockContext context)
|
||||||
|
|
|
@ -6,21 +6,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
{
|
{
|
||||||
private TimeSpanType _standardNetworkClockSufficientAccuracy;
|
private TimeSpanType _standardNetworkClockSufficientAccuracy;
|
||||||
|
|
||||||
private static StandardNetworkSystemClockCore _instance;
|
|
||||||
|
|
||||||
public static StandardNetworkSystemClockCore Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
_instance = new StandardNetworkSystemClockCore(StandardSteadyClockCore.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StandardNetworkSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore)
|
public StandardNetworkSystemClockCore(StandardSteadyClockCore steadyClockCore) : base(steadyClockCore)
|
||||||
{
|
{
|
||||||
_standardNetworkClockSufficientAccuracy = new TimeSpanType(0);
|
_standardNetworkClockSufficientAccuracy = new TimeSpanType(0);
|
||||||
|
|
|
@ -7,27 +7,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
{
|
{
|
||||||
private TimeSpanType _setupValue;
|
private TimeSpanType _setupValue;
|
||||||
// TODO: move this to glue when we will have psc fully done
|
// TODO: move this to glue when we will have psc fully done
|
||||||
//private ResultCode _setupResultCode;
|
private ResultCode _setupResultCode;
|
||||||
private TimeSpanType _testOffset;
|
private TimeSpanType _testOffset;
|
||||||
private TimeSpanType _internalOffset;
|
private TimeSpanType _internalOffset;
|
||||||
private TimeSpanType _cachedRawTimePoint;
|
private TimeSpanType _cachedRawTimePoint;
|
||||||
|
|
||||||
private static StandardSteadyClockCore _instance;
|
public StandardSteadyClockCore()
|
||||||
|
|
||||||
public static StandardSteadyClockCore Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
_instance = new StandardSteadyClockCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private StandardSteadyClockCore()
|
|
||||||
{
|
{
|
||||||
_setupValue = new TimeSpanType(0);
|
_setupValue = new TimeSpanType(0);
|
||||||
_testOffset = new TimeSpanType(0);
|
_testOffset = new TimeSpanType(0);
|
||||||
|
@ -83,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: move this to glue when we will have psc fully done
|
// TODO: move this to glue when we will have psc fully done
|
||||||
/*public void ConfigureSetupValue()
|
public void ConfigureSetupValue()
|
||||||
{
|
{
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
|
|
||||||
|
@ -103,6 +88,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
}
|
}
|
||||||
|
|
||||||
_setupResultCode = result;
|
_setupResultCode = result;
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,21 +8,6 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
private StandardNetworkSystemClockCore _networkSystemClockCore;
|
private StandardNetworkSystemClockCore _networkSystemClockCore;
|
||||||
private bool _autoCorrectionEnabled;
|
private bool _autoCorrectionEnabled;
|
||||||
|
|
||||||
private static StandardUserSystemClockCore _instance;
|
|
||||||
|
|
||||||
public static StandardUserSystemClockCore Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
_instance = new StandardUserSystemClockCore(StandardLocalSystemClockCore.Instance, StandardNetworkSystemClockCore.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StandardUserSystemClockCore(StandardLocalSystemClockCore localSystemClockCore, StandardNetworkSystemClockCore networkSystemClockCore) : base(localSystemClockCore.GetSteadyClockCore())
|
public StandardUserSystemClockCore(StandardLocalSystemClockCore localSystemClockCore, StandardNetworkSystemClockCore networkSystemClockCore) : base(localSystemClockCore.GetSteadyClockCore())
|
||||||
{
|
{
|
||||||
_localSystemClockCore = localSystemClockCore;
|
_localSystemClockCore = localSystemClockCore;
|
||||||
|
|
|
@ -4,22 +4,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.Clock
|
||||||
{
|
{
|
||||||
class TickBasedSteadyClockCore : SteadyClockCore
|
class TickBasedSteadyClockCore : SteadyClockCore
|
||||||
{
|
{
|
||||||
private static TickBasedSteadyClockCore _instance;
|
public TickBasedSteadyClockCore() {}
|
||||||
|
|
||||||
public static TickBasedSteadyClockCore Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
_instance = new TickBasedSteadyClockCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TickBasedSteadyClockCore() {}
|
|
||||||
|
|
||||||
public override SteadyClockTimePoint GetTimePoint(KThread thread)
|
public override SteadyClockTimePoint GetTimePoint(KThread thread)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,25 +15,27 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
//[Service("time:a", TimePermissions.Admin)]
|
//[Service("time:a", TimePermissions.Admin)]
|
||||||
[Service("time:s", TimePermissions.System)]
|
[Service("time:s", TimePermissions.System)]
|
||||||
//[Service("time:u", TimePermissions.User)]
|
//[Service("time:u", TimePermissions.User)]
|
||||||
[Service("time:su", TimePermissions.System)]
|
[Service("time:su", TimePermissions.SystemUpdate)]
|
||||||
class IStaticService : IpcService
|
class IStaticService : IpcService
|
||||||
{
|
{
|
||||||
|
private TimeManager _timeManager;
|
||||||
private TimePermissions _permissions;
|
private TimePermissions _permissions;
|
||||||
|
|
||||||
private int _timeSharedMemoryNativeHandle = 0;
|
private int _timeSharedMemoryNativeHandle = 0;
|
||||||
|
|
||||||
private static readonly DateTime StartupDate = DateTime.UtcNow;
|
public IStaticService(ServiceCtx context, TimePermissions permissions) : this(TimeManager.Instance, permissions) {}
|
||||||
|
|
||||||
public IStaticService(ServiceCtx context, TimePermissions permissions)
|
public IStaticService(TimeManager manager, TimePermissions permissions)
|
||||||
{
|
{
|
||||||
_permissions = permissions;
|
_permissions = permissions;
|
||||||
|
_timeManager = manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command(0)]
|
[Command(0)]
|
||||||
// GetStandardUserSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
// GetStandardUserSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||||
public ResultCode GetStandardUserSystemClock(ServiceCtx context)
|
public ResultCode GetStandardUserSystemClock(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ISystemClock(StandardUserSystemClockCore.Instance, (_permissions & TimePermissions.UserSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
MakeObject(context, new ISystemClock(_timeManager.StandardUserSystemClock, (_permissions & TimePermissions.UserSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// GetStandardNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
// GetStandardNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||||
public ResultCode GetStandardNetworkSystemClock(ServiceCtx context)
|
public ResultCode GetStandardNetworkSystemClock(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
MakeObject(context, new ISystemClock(_timeManager.StandardNetworkSystemClock, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// GetStandardSteadyClock() -> object<nn::timesrv::detail::service::ISteadyClock>
|
// GetStandardSteadyClock() -> object<nn::timesrv::detail::service::ISteadyClock>
|
||||||
public ResultCode GetStandardSteadyClock(ServiceCtx context)
|
public ResultCode GetStandardSteadyClock(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ISteadyClock(StandardSteadyClockCore.Instance, (_permissions & TimePermissions.SteadyClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
MakeObject(context, new ISteadyClock(_timeManager.StandardSteadyClock, (_permissions & TimePermissions.SteadyClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +62,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// GetTimeZoneService() -> object<nn::timesrv::detail::service::ITimeZoneService>
|
// GetTimeZoneService() -> object<nn::timesrv::detail::service::ITimeZoneService>
|
||||||
public ResultCode GetTimeZoneService(ServiceCtx context)
|
public ResultCode GetTimeZoneService(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ITimeZoneService());
|
MakeObject(context, new ITimeZoneService(_timeManager.TimeZone, (_permissions & TimePermissions.TimeZoneWritableMask) != 0));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// GetStandardLocalSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
// GetStandardLocalSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||||
public ResultCode GetStandardLocalSystemClock(ServiceCtx context)
|
public ResultCode GetStandardLocalSystemClock(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ISystemClock(StandardLocalSystemClockCore.Instance, (_permissions & TimePermissions.LocalSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
MakeObject(context, new ISystemClock(_timeManager.StandardLocalSystemClock, (_permissions & TimePermissions.LocalSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -78,7 +80,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// GetEphemeralNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
// GetEphemeralNetworkSystemClock() -> object<nn::timesrv::detail::service::ISystemClock>
|
||||||
public ResultCode GetEphemeralNetworkSystemClock(ServiceCtx context)
|
public ResultCode GetEphemeralNetworkSystemClock(ServiceCtx context)
|
||||||
{
|
{
|
||||||
MakeObject(context, new ISystemClock(StandardNetworkSystemClockCore.Instance, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
MakeObject(context, new ISystemClock(_timeManager.StandardNetworkSystemClock, (_permissions & TimePermissions.NetworkSystemClockWritableMask) != 0, (_permissions & TimePermissions.BypassUninitialized) != 0));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// IsStandardUserSystemClockAutomaticCorrectionEnabled() -> bool
|
// IsStandardUserSystemClockAutomaticCorrectionEnabled() -> bool
|
||||||
public ResultCode IsStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
|
public ResultCode IsStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
|
||||||
{
|
{
|
||||||
StandardUserSystemClockCore userClock = StandardUserSystemClockCore.Instance;
|
StandardUserSystemClockCore userClock = _timeManager.StandardUserSystemClock;
|
||||||
|
|
||||||
if (!userClock.IsInitialized())
|
if (!userClock.IsInitialized())
|
||||||
{
|
{
|
||||||
|
@ -120,8 +122,8 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// SetStandardUserSystemClockAutomaticCorrectionEnabled(b8)
|
// SetStandardUserSystemClockAutomaticCorrectionEnabled(b8)
|
||||||
public ResultCode SetStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
|
public ResultCode SetStandardUserSystemClockAutomaticCorrectionEnabled(ServiceCtx context)
|
||||||
{
|
{
|
||||||
SteadyClockCore steadyClock = StandardSteadyClockCore.Instance;
|
SteadyClockCore steadyClock = _timeManager.StandardSteadyClock;
|
||||||
StandardUserSystemClockCore userClock = StandardUserSystemClockCore.Instance;
|
StandardUserSystemClockCore userClock = _timeManager.StandardUserSystemClock;
|
||||||
|
|
||||||
if (!userClock.IsInitialized() || !steadyClock.IsInitialized())
|
if (!userClock.IsInitialized() || !steadyClock.IsInitialized())
|
||||||
{
|
{
|
||||||
|
@ -135,14 +137,14 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
|
||||||
bool autoCorrectionEnabled = context.RequestData.ReadBoolean();
|
bool autoCorrectionEnabled = context.RequestData.ReadBoolean();
|
||||||
|
|
||||||
return StandardUserSystemClockCore.Instance.SetAutomaticCorrectionEnabled(context.Thread, autoCorrectionEnabled);
|
return userClock.SetAutomaticCorrectionEnabled(context.Thread, autoCorrectionEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command(200)] // 3.0.0+
|
[Command(200)] // 3.0.0+
|
||||||
// IsStandardNetworkSystemClockAccuracySufficient() -> bool
|
// IsStandardNetworkSystemClockAccuracySufficient() -> bool
|
||||||
public ResultCode IsStandardNetworkSystemClockAccuracySufficient(ServiceCtx context)
|
public ResultCode IsStandardNetworkSystemClockAccuracySufficient(ServiceCtx context)
|
||||||
{
|
{
|
||||||
context.ResponseData.Write(StandardNetworkSystemClockCore.Instance.IsStandardNetworkSystemClockAccuracySufficient(context.Thread));
|
context.ResponseData.Write(_timeManager.StandardNetworkSystemClock.IsStandardNetworkSystemClockAccuracySufficient(context.Thread));
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +153,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
// CalculateMonotonicSystemClockBaseTimePoint(nn::time::SystemClockContext) -> s64
|
// CalculateMonotonicSystemClockBaseTimePoint(nn::time::SystemClockContext) -> s64
|
||||||
public ResultCode CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx context)
|
public ResultCode CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx context)
|
||||||
{
|
{
|
||||||
SteadyClockCore steadyClock = StandardSteadyClockCore.Instance;
|
SteadyClockCore steadyClock = _timeManager.StandardSteadyClock;
|
||||||
|
|
||||||
if (!steadyClock.IsInitialized())
|
if (!steadyClock.IsInitialized())
|
||||||
{
|
{
|
||||||
|
@ -182,11 +184,11 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
{
|
{
|
||||||
byte type = context.RequestData.ReadByte();
|
byte type = context.RequestData.ReadByte();
|
||||||
|
|
||||||
ResultCode result = StandardUserSystemClockCore.Instance.GetClockContext(context.Thread, out SystemClockContext userContext);
|
ResultCode result = _timeManager.StandardUserSystemClock.GetClockContext(context.Thread, out SystemClockContext userContext);
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
result = StandardNetworkSystemClockCore.Instance.GetClockContext(context.Thread, out SystemClockContext networkContext);
|
result = _timeManager.StandardNetworkSystemClock.GetClockContext(context.Thread, out SystemClockContext networkContext);
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
|
@ -280,14 +282,14 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
{
|
{
|
||||||
clockSnapshot = new ClockSnapshot();
|
clockSnapshot = new ClockSnapshot();
|
||||||
|
|
||||||
SteadyClockCore steadyClockCore = StandardSteadyClockCore.Instance;
|
SteadyClockCore steadyClockCore = _timeManager.StandardSteadyClock;
|
||||||
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(thread);
|
SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(thread);
|
||||||
|
|
||||||
clockSnapshot.IsAutomaticCorrectionEnabled = StandardUserSystemClockCore.Instance.IsAutomaticCorrectionEnabled();
|
clockSnapshot.IsAutomaticCorrectionEnabled = _timeManager.StandardUserSystemClock.IsAutomaticCorrectionEnabled();
|
||||||
clockSnapshot.UserContext = userContext;
|
clockSnapshot.UserContext = userContext;
|
||||||
clockSnapshot.NetworkContext = networkContext;
|
clockSnapshot.NetworkContext = networkContext;
|
||||||
|
|
||||||
char[] tzName = TimeZoneManager.Instance.GetDeviceLocationName().ToCharArray();
|
char[] tzName = _timeManager.TimeZone.GetDeviceLocationName().ToCharArray();
|
||||||
char[] locationName = new char[0x24];
|
char[] locationName = new char[0x24];
|
||||||
|
|
||||||
Array.Copy(tzName, locationName, tzName.Length);
|
Array.Copy(tzName, locationName, tzName.Length);
|
||||||
|
@ -298,7 +300,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
result = TimeZoneManager.Instance.ToCalendarTimeWithMyRules(clockSnapshot.UserTime, out CalendarInfo userCalendarInfo);
|
result = _timeManager.TimeZone.ToCalendarTimeWithMyRules(clockSnapshot.UserTime, out CalendarInfo userCalendarInfo);
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
|
@ -310,7 +312,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
clockSnapshot.NetworkTime = 0;
|
clockSnapshot.NetworkTime = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = TimeZoneManager.Instance.ToCalendarTimeWithMyRules(clockSnapshot.NetworkTime, out CalendarInfo networkCalendarInfo);
|
result = _timeManager.TimeZone.ToCalendarTimeWithMyRules(clockSnapshot.NetworkTime, out CalendarInfo networkCalendarInfo);
|
||||||
|
|
||||||
if (result == ResultCode.Success)
|
if (result == ResultCode.Success)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,13 +9,20 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
{
|
{
|
||||||
class ITimeZoneService : IpcService
|
class ITimeZoneService : IpcService
|
||||||
{
|
{
|
||||||
public ITimeZoneService() { }
|
private TimeZoneManager _timeZoneManager;
|
||||||
|
private bool _writePermission;
|
||||||
|
|
||||||
|
public ITimeZoneService(TimeZoneManager timeZoneManager, bool writePermission)
|
||||||
|
{
|
||||||
|
_timeZoneManager = timeZoneManager;
|
||||||
|
_writePermission = writePermission;
|
||||||
|
}
|
||||||
|
|
||||||
[Command(0)]
|
[Command(0)]
|
||||||
// GetDeviceLocationName() -> nn::time::LocationName
|
// GetDeviceLocationName() -> nn::time::LocationName
|
||||||
public ResultCode GetDeviceLocationName(ServiceCtx context)
|
public ResultCode GetDeviceLocationName(ServiceCtx context)
|
||||||
{
|
{
|
||||||
char[] tzName = TimeZoneManager.Instance.GetDeviceLocationName().ToCharArray();
|
char[] tzName = _timeZoneManager.GetDeviceLocationName().ToCharArray();
|
||||||
|
|
||||||
int padding = 0x24 - tzName.Length;
|
int padding = 0x24 - tzName.Length;
|
||||||
|
|
||||||
|
@ -38,16 +45,21 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
// SetDeviceLocationName(nn::time::LocationName)
|
// SetDeviceLocationName(nn::time::LocationName)
|
||||||
public ResultCode SetDeviceLocationName(ServiceCtx context)
|
public ResultCode SetDeviceLocationName(ServiceCtx context)
|
||||||
{
|
{
|
||||||
|
if (!_writePermission)
|
||||||
|
{
|
||||||
|
return ResultCode.PermissionDenied;
|
||||||
|
}
|
||||||
|
|
||||||
string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0');
|
string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0');
|
||||||
|
|
||||||
return TimeZoneManager.Instance.SetDeviceLocationName(locationName);
|
return _timeZoneManager.SetDeviceLocationName(locationName);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Command(2)]
|
[Command(2)]
|
||||||
// GetTotalLocationNameCount() -> u32
|
// GetTotalLocationNameCount() -> u32
|
||||||
public ResultCode GetTotalLocationNameCount(ServiceCtx context)
|
public ResultCode GetTotalLocationNameCount(ServiceCtx context)
|
||||||
{
|
{
|
||||||
context.ResponseData.Write(TimeZoneManager.Instance.GetTotalLocationNameCount());
|
context.ResponseData.Write(_timeZoneManager.GetTotalLocationNameCount());
|
||||||
|
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
long bufferPosition = context.Request.ReceiveBuff[0].Position;
|
long bufferPosition = context.Request.ReceiveBuff[0].Position;
|
||||||
long bufferSize = context.Request.ReceiveBuff[0].Size;
|
long bufferSize = context.Request.ReceiveBuff[0].Size;
|
||||||
|
|
||||||
ResultCode errorCode = TimeZoneManager.Instance.LoadLocationNameList(index, out string[] locationNameArray, (uint)bufferSize / 0x24);
|
ResultCode errorCode = _timeZoneManager.LoadLocationNameList(index, out string[] locationNameArray, (uint)bufferSize / 0x24);
|
||||||
|
|
||||||
if (errorCode == 0)
|
if (errorCode == 0)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
|
|
||||||
string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0');
|
string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0');
|
||||||
|
|
||||||
ResultCode resultCode = TimeZoneManager.Instance.LoadTimeZoneRules(out TimeZoneRule rules, locationName);
|
ResultCode resultCode = _timeZoneManager.LoadTimeZoneRules(out TimeZoneRule rules, locationName);
|
||||||
|
|
||||||
// Write TimeZoneRule if success
|
// Write TimeZoneRule if success
|
||||||
if (resultCode == 0)
|
if (resultCode == 0)
|
||||||
|
@ -150,7 +162,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
{
|
{
|
||||||
long posixTime = context.RequestData.ReadInt64();
|
long posixTime = context.RequestData.ReadInt64();
|
||||||
|
|
||||||
ResultCode resultCode = TimeZoneManager.Instance.ToCalendarTimeWithMyRules(posixTime, out CalendarInfo calendar);
|
ResultCode resultCode = _timeZoneManager.ToCalendarTimeWithMyRules(posixTime, out CalendarInfo calendar);
|
||||||
|
|
||||||
if (resultCode == 0)
|
if (resultCode == 0)
|
||||||
{
|
{
|
||||||
|
@ -199,7 +211,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.StaticService
|
||||||
{
|
{
|
||||||
CalendarTime calendarTime = context.RequestData.ReadStruct<CalendarTime>();
|
CalendarTime calendarTime = context.RequestData.ReadStruct<CalendarTime>();
|
||||||
|
|
||||||
ResultCode resultCode = TimeZoneManager.Instance.ToPosixTimeWithMyRules(calendarTime, out long posixTime);
|
ResultCode resultCode = _timeZoneManager.ToPosixTimeWithMyRules(calendarTime, out long posixTime);
|
||||||
|
|
||||||
if (resultCode == 0)
|
if (resultCode == 0)
|
||||||
{
|
{
|
||||||
|
|
47
Ryujinx.HLE/HOS/Services/Time/TimeManager.cs
Normal file
47
Ryujinx.HLE/HOS/Services/Time/TimeManager.cs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Time.TimeZone;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
{
|
||||||
|
class TimeManager
|
||||||
|
{
|
||||||
|
private static TimeManager _instance;
|
||||||
|
|
||||||
|
public static TimeManager Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
_instance = new TimeManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StandardSteadyClockCore StandardSteadyClock { get; private set; }
|
||||||
|
public TickBasedSteadyClockCore TickBasedSteadyClock { get; private set; }
|
||||||
|
public StandardLocalSystemClockCore StandardLocalSystemClock { get; private set; }
|
||||||
|
public StandardNetworkSystemClockCore StandardNetworkSystemClock { get; private set; }
|
||||||
|
public StandardUserSystemClockCore StandardUserSystemClock { get; private set; }
|
||||||
|
public TimeZoneManager TimeZone { get; private set; }
|
||||||
|
public EphemeralNetworkSystemClockCore EphemeralNetworkSystemClock { get; private set; }
|
||||||
|
|
||||||
|
// TODO: 9.0.0+ power state, alarms, clock writers
|
||||||
|
|
||||||
|
public TimeManager()
|
||||||
|
{
|
||||||
|
StandardSteadyClock = new StandardSteadyClockCore();
|
||||||
|
TickBasedSteadyClock = new TickBasedSteadyClockCore();
|
||||||
|
StandardLocalSystemClock = new StandardLocalSystemClockCore(StandardSteadyClock);
|
||||||
|
StandardNetworkSystemClock = new StandardNetworkSystemClockCore(StandardSteadyClock);
|
||||||
|
StandardUserSystemClock = new StandardUserSystemClockCore(StandardLocalSystemClock, StandardNetworkSystemClock);
|
||||||
|
TimeZone = new TimeZoneManager();
|
||||||
|
EphemeralNetworkSystemClock = new EphemeralNetworkSystemClockCore(StandardSteadyClock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -26,23 +26,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
||||||
private string _deviceLocationName;
|
private string _deviceLocationName;
|
||||||
private string[] _locationNameCache;
|
private string[] _locationNameCache;
|
||||||
|
|
||||||
public static TimeZoneManager Instance
|
public TimeZoneManager()
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
lock (instanceLock)
|
|
||||||
{
|
|
||||||
if (instance == null)
|
|
||||||
{
|
|
||||||
instance = new TimeZoneManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeZoneManager()
|
|
||||||
{
|
{
|
||||||
// Empty rules (UTC)
|
// Empty rules (UTC)
|
||||||
_myRules = new TimeZoneRule
|
_myRules = new TimeZoneRule
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue