|
|
@@ -4,8 +4,10 @@ using LibHac.Fs;
|
|
|
using LibHac.FsSystem;
|
|
|
using LibHac.FsSystem.NcaUtils;
|
|
|
using Ryujinx.Common.Logging;
|
|
|
+using Ryujinx.Configuration;
|
|
|
using Ryujinx.HLE.Exceptions;
|
|
|
using Ryujinx.HLE.FileSystem;
|
|
|
+using Ryujinx.HLE.FileSystem.Content;
|
|
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
|
|
using Ryujinx.HLE.Utilities;
|
|
|
using System.Collections.Generic;
|
|
|
@@ -15,34 +17,62 @@ using static Ryujinx.HLE.HOS.Services.Time.TimeZone.TimeZoneRule;
|
|
|
|
|
|
namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|
|
{
|
|
|
- class TimeZoneContentManager
|
|
|
+ public class TimeZoneContentManager
|
|
|
{
|
|
|
private const long TimeZoneBinaryTitleId = 0x010000000000080E;
|
|
|
|
|
|
- private Switch _device;
|
|
|
- private string[] _locationNameCache;
|
|
|
+ private VirtualFileSystem _virtualFileSystem;
|
|
|
+ private IntegrityCheckLevel _fsIntegrityCheckLevel;
|
|
|
+ private ContentManager _contentManager;
|
|
|
|
|
|
- public TimeZoneManager Manager { get; private set; }
|
|
|
+ public string[] LocationNameCache { get; private set; }
|
|
|
+
|
|
|
+ internal TimeZoneManager Manager { get; private set; }
|
|
|
|
|
|
public TimeZoneContentManager()
|
|
|
{
|
|
|
Manager = new TimeZoneManager();
|
|
|
}
|
|
|
|
|
|
- internal void Initialize(TimeManager timeManager, Switch device)
|
|
|
+ public void InitializeInstance(VirtualFileSystem virtualFileSystem, ContentManager contentManager, IntegrityCheckLevel fsIntegrityCheckLevel)
|
|
|
{
|
|
|
- _device = device;
|
|
|
+ _virtualFileSystem = virtualFileSystem;
|
|
|
+ _contentManager = contentManager;
|
|
|
+ _fsIntegrityCheckLevel = fsIntegrityCheckLevel;
|
|
|
|
|
|
InitializeLocationNameCache();
|
|
|
+ }
|
|
|
+
|
|
|
+ public string SanityCheckDeviceLocationName()
|
|
|
+ {
|
|
|
+ string locationName = ConfigurationState.Instance.System.TimeZone;
|
|
|
+
|
|
|
+ if (IsLocationNameValid(locationName))
|
|
|
+ {
|
|
|
+ return locationName;
|
|
|
+ }
|
|
|
+
|
|
|
+ Logger.PrintWarning(LogClass.ServiceTime, $"Invalid device TimeZone {locationName}, switching back to UTC");
|
|
|
+
|
|
|
+ ConfigurationState.Instance.System.TimeZone.Value = "UTC";
|
|
|
+
|
|
|
+ return "UTC";
|
|
|
+ }
|
|
|
+
|
|
|
+ internal void Initialize(TimeManager timeManager, Switch device)
|
|
|
+ {
|
|
|
+ InitializeInstance(device.FileSystem, device.System.ContentManager, device.System.FsIntegrityCheckLevel);
|
|
|
|
|
|
SteadyClockTimePoint timeZoneUpdatedTimePoint = timeManager.StandardSteadyClock.GetCurrentTimePoint(null);
|
|
|
|
|
|
- ResultCode result = GetTimeZoneBinary("UTC", out Stream timeZoneBinaryStream, out LocalStorage ncaFile);
|
|
|
+ string deviceLocationName = SanityCheckDeviceLocationName();
|
|
|
+
|
|
|
+ ResultCode result = GetTimeZoneBinary(deviceLocationName, out Stream timeZoneBinaryStream, out LocalStorage ncaFile);
|
|
|
|
|
|
if (result == ResultCode.Success)
|
|
|
{
|
|
|
// TODO: Read TimeZoneVersion from sysarchive.
|
|
|
- timeManager.SetupTimeZoneManager("UTC", timeZoneUpdatedTimePoint, (uint)_locationNameCache.Length, new UInt128(), timeZoneBinaryStream);
|
|
|
+ timeManager.SetupTimeZoneManager(deviceLocationName, timeZoneUpdatedTimePoint, (uint)LocationNameCache.Length, new UInt128(), timeZoneBinaryStream);
|
|
|
|
|
|
ncaFile.Dispose();
|
|
|
}
|
|
|
@@ -57,10 +87,10 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|
|
{
|
|
|
if (HasTimeZoneBinaryTitle())
|
|
|
{
|
|
|
- using (IStorage ncaFileStream = new LocalStorage(_device.FileSystem.SwitchPathToSystemPath(GetTimeZoneBinaryTitleContentPath()), FileAccess.Read, FileMode.Open))
|
|
|
+ using (IStorage ncaFileStream = new LocalStorage(_virtualFileSystem.SwitchPathToSystemPath(GetTimeZoneBinaryTitleContentPath()), FileAccess.Read, FileMode.Open))
|
|
|
{
|
|
|
- Nca nca = new Nca(_device.System.KeySet, ncaFileStream);
|
|
|
- IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel);
|
|
|
+ Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFileStream);
|
|
|
+ IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _fsIntegrityCheckLevel);
|
|
|
|
|
|
romfs.OpenFile(out IFile binaryListFile, "/binaryList.txt".ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
|
|
|
|
|
@@ -74,12 +104,12 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|
|
locationNameList.Add(locationName);
|
|
|
}
|
|
|
|
|
|
- _locationNameCache = locationNameList.ToArray();
|
|
|
+ LocationNameCache = locationNameList.ToArray();
|
|
|
}
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- _locationNameCache = new string[0];
|
|
|
+ LocationNameCache = new string[] { "UTC" };
|
|
|
|
|
|
Logger.PrintWarning(LogClass.ServiceTime, "TimeZoneBinary system title not found! TimeZone conversions will not work, provide the system archive to fix this warning. (See https://github.com/Ryujinx/Ryujinx#requirements for more informations)");
|
|
|
}
|
|
|
@@ -87,7 +117,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|
|
|
|
|
private bool IsLocationNameValid(string locationName)
|
|
|
{
|
|
|
- foreach (string cachedLocationName in _locationNameCache)
|
|
|
+ foreach (string cachedLocationName in LocationNameCache)
|
|
|
{
|
|
|
if (cachedLocationName.Equals(locationName))
|
|
|
{
|
|
|
@@ -116,14 +146,14 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|
|
{
|
|
|
List<string> locationNameList = new List<string>();
|
|
|
|
|
|
- for (int i = 0; i < _locationNameCache.Length && i < maxLength; i++)
|
|
|
+ for (int i = 0; i < LocationNameCache.Length && i < maxLength; i++)
|
|
|
{
|
|
|
if (i < index)
|
|
|
{
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
- string locationName = _locationNameCache[i];
|
|
|
+ string locationName = LocationNameCache[i];
|
|
|
|
|
|
// If the location name is too long, error out.
|
|
|
if (locationName.Length > 0x24)
|
|
|
@@ -143,7 +173,7 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|
|
|
|
|
public string GetTimeZoneBinaryTitleContentPath()
|
|
|
{
|
|
|
- return _device.System.ContentManager.GetInstalledContentPath(TimeZoneBinaryTitleId, StorageId.NandSystem, NcaContentType.Data);
|
|
|
+ return _contentManager.GetInstalledContentPath(TimeZoneBinaryTitleId, StorageId.NandSystem, NcaContentType.Data);
|
|
|
}
|
|
|
|
|
|
public bool HasTimeZoneBinaryTitle()
|
|
|
@@ -161,10 +191,10 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone
|
|
|
return ResultCode.TimeZoneNotFound;
|
|
|
}
|
|
|
|
|
|
- ncaFile = new LocalStorage(_device.FileSystem.SwitchPathToSystemPath(GetTimeZoneBinaryTitleContentPath()), FileAccess.Read, FileMode.Open);
|
|
|
+ ncaFile = new LocalStorage(_virtualFileSystem.SwitchPathToSystemPath(GetTimeZoneBinaryTitleContentPath()), FileAccess.Read, FileMode.Open);
|
|
|
|
|
|
- Nca nca = new Nca(_device.System.KeySet, ncaFile);
|
|
|
- IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _device.System.FsIntegrityCheckLevel);
|
|
|
+ Nca nca = new Nca(_virtualFileSystem.KeySet, ncaFile);
|
|
|
+ IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, _fsIntegrityCheckLevel);
|
|
|
|
|
|
Result result = romfs.OpenFile(out IFile timeZoneBinaryFile, $"/zoneinfo/{locationName}".ToU8Span(), OpenMode.Read);
|
|
|
|