diff options
Diffstat (limited to 'Ryujinx.HLE/HOS')
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs index 70e1dcb4..e2576425 100644 --- a/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs +++ b/Ryujinx.HLE/HOS/Services/Time/TimeZone/TimeZoneContentManager.cs @@ -10,6 +10,7 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem.Content; using Ryujinx.HLE.HOS.Services.Time.Clock; using Ryujinx.HLE.Utilities; +using System; using System.Collections.Generic; using System.IO; @@ -117,6 +118,73 @@ namespace Ryujinx.HLE.HOS.Services.Time.TimeZone } } + public IEnumerable<(int Offset, string Location, string Abbr)> ParseTzOffsets() + { + var tzBinaryContentPath = GetTimeZoneBinaryTitleContentPath(); + + if (string.IsNullOrEmpty(tzBinaryContentPath)) + { + return new[] { (0, "UTC", "UTC") }; + } + + List<(int Offset, string Location, string Abbr)> outList = new List<(int Offset, string Location, string Abbr)>(); + var now = System.DateTimeOffset.Now.ToUnixTimeSeconds(); + using (IStorage ncaStorage = new LocalStorage(_virtualFileSystem.SwitchPathToSystemPath(tzBinaryContentPath), FileAccess.Read, FileMode.Open)) + using (IFileSystem romfs = new Nca(_virtualFileSystem.KeySet, ncaStorage).OpenFileSystem(NcaSectionType.Data, _fsIntegrityCheckLevel)) + { + foreach (string locName in LocationNameCache) + { + if (locName.StartsWith("Etc")) + { + continue; + } + + if (romfs.OpenFile(out IFile tzif, $"/zoneinfo/{locName}".ToU8Span(), OpenMode.Read).IsFailure()) + { + Logger.PrintError(LogClass.ServiceTime, $"Error opening /zoneinfo/{locName}"); + continue; + } + + using (tzif) + { + TimeZone.ParseTimeZoneBinary(out TimeZoneRule tzRule, tzif.AsStream()); + + TimeTypeInfo ttInfo; + if (tzRule.TimeCount > 0) // Find the current transition period + { + int fin = 0; + for (int i = 0; i < tzRule.TimeCount; ++i) + { + if (tzRule.Ats[i] <= now) + { + fin = i; + } + } + ttInfo = tzRule.Ttis[tzRule.Types[fin]]; + } + else if (tzRule.TypeCount >= 1) // Otherwise, use the first offset in TTInfo + { + ttInfo = tzRule.Ttis[0]; + } + else + { + Logger.PrintError(LogClass.ServiceTime, $"Couldn't find UTC offset for zone {locName}"); + continue; + } + + var abbrStart = tzRule.Chars.AsSpan(ttInfo.AbbreviationListIndex); + int abbrEnd = abbrStart.IndexOf('\0'); + + outList.Add((ttInfo.GmtOffset, locName, abbrStart.Slice(0, abbrEnd).ToString())); + } + } + } + + outList.Sort(); + + return outList; + } + private bool IsLocationNameValid(string locationName) { foreach (string cachedLocationName in LocationNameCache) |
