diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-08-16 20:47:36 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-08-16 20:47:36 -0300 |
| commit | 521751795a1c97c0d97f6f8904a3be69b13d3a9d (patch) | |
| tree | 942a05899c40e2de6d92a38b93a494bd96ee64b8 /Ryujinx.HLE/HOS/Services/Time | |
| parent | 182d716867ae477c2b15a5332430dc2641fa1cc3 (diff) | |
Code style fixes and nits on the HLE project (#355)
* Some style fixes and nits on ITimeZoneService
* Remove some unneeded usings
* Remove the Ryujinx.HLE.OsHle.Handles namespace
* Remove hbmenu automatic load on process exit
* Rename Ns to Device, rename Os to System, rename SystemState to State
* Move Exceptions and Utilities out of OsHle
* Rename OsHle to HOS
* Rename OsHle folder to HOS
* IManagerDisplayService and ISystemDisplayService style fixes
* BsdError shouldn't be public
* Add a empty new line before using static
* Remove unused file
* Some style fixes on NPDM
* Exit gracefully when the application is closed
* Code style fixes on IGeneralService
* Add 0x prefix on values printed as hex
* Small improvements on finalization code
* Move ProcessId and ThreadId out of AThreadState
* Rename VFs to FileSystem
* FsAccessHeader shouldn't be public. Also fix file names casing
* More case changes on NPDM
* Remove unused files
* Move using to the correct place on NPDM
* Use properties on KernelAccessControlMmio
* Address PR feedback
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Time')
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Time/IStaticService.cs | 74 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Time/ISteadyClock.cs | 53 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Time/ISystemClock.cs | 107 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Time/ITimeZoneService.cs | 280 | ||||
| -rw-r--r-- | Ryujinx.HLE/HOS/Services/Time/SystemClockType.cs | 10 |
5 files changed, 524 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Time/IStaticService.cs b/Ryujinx.HLE/HOS/Services/Time/IStaticService.cs new file mode 100644 index 00000000..66f16501 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/IStaticService.cs @@ -0,0 +1,74 @@ +using Ryujinx.HLE.HOS.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Services.Time +{ + class IStaticService : IpcService + { + private Dictionary<int, ServiceProcessRequest> m_Commands; + + public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands; + + private static readonly DateTime StartupDate = DateTime.UtcNow; + + public IStaticService() + { + m_Commands = new Dictionary<int, ServiceProcessRequest>() + { + { 0, GetStandardUserSystemClock }, + { 1, GetStandardNetworkSystemClock }, + { 2, GetStandardSteadyClock }, + { 3, GetTimeZoneService }, + { 4, GetStandardLocalSystemClock }, + { 300, CalculateMonotonicSystemClockBaseTimePoint } + }; + } + + public long GetStandardUserSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.User)); + + return 0; + } + + public long GetStandardNetworkSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.Network)); + + return 0; + } + + public long GetStandardSteadyClock(ServiceCtx Context) + { + MakeObject(Context, new ISteadyClock()); + + return 0; + } + + public long GetTimeZoneService(ServiceCtx Context) + { + MakeObject(Context, new ITimeZoneService()); + + return 0; + } + + public long GetStandardLocalSystemClock(ServiceCtx Context) + { + MakeObject(Context, new ISystemClock(SystemClockType.Local)); + + return 0; + } + + public long CalculateMonotonicSystemClockBaseTimePoint(ServiceCtx Context) + { + long TimeOffset = (long)(DateTime.UtcNow - StartupDate).TotalSeconds; + long SystemClockContextEpoch = Context.RequestData.ReadInt64(); + + Context.ResponseData.Write(TimeOffset + SystemClockContextEpoch); + + return 0; + } + + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Time/ISteadyClock.cs b/Ryujinx.HLE/HOS/Services/Time/ISteadyClock.cs new file mode 100644 index 00000000..e4020bb1 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/ISteadyClock.cs @@ -0,0 +1,53 @@ +using Ryujinx.HLE.HOS.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Services.Time +{ + class ISteadyClock : IpcService + { + private Dictionary<int, ServiceProcessRequest> m_Commands; + + public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands; + + private ulong TestOffset; + + public ISteadyClock() + { + m_Commands = new Dictionary<int, ServiceProcessRequest>() + { + { 0, GetCurrentTimePoint }, + { 1, GetTestOffset }, + { 2, SetTestOffset } + }; + + TestOffset = 0; + } + + public long GetCurrentTimePoint(ServiceCtx Context) + { + Context.ResponseData.Write((long)(System.Diagnostics.Process.GetCurrentProcess().StartTime - DateTime.Now).TotalSeconds); + + for (int i = 0; i < 0x10; i++) + { + Context.ResponseData.Write((byte)0); + } + + return 0; + } + + public long GetTestOffset(ServiceCtx Context) + { + Context.ResponseData.Write(TestOffset); + + return 0; + } + + public long SetTestOffset(ServiceCtx Context) + { + TestOffset = Context.RequestData.ReadUInt64(); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Time/ISystemClock.cs b/Ryujinx.HLE/HOS/Services/Time/ISystemClock.cs new file mode 100644 index 00000000..f574826a --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/ISystemClock.cs @@ -0,0 +1,107 @@ +using Ryujinx.HLE.HOS.Ipc; +using System; +using System.Collections.Generic; + +namespace Ryujinx.HLE.HOS.Services.Time +{ + class ISystemClock : IpcService + { + private Dictionary<int, ServiceProcessRequest> m_Commands; + + public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands; + + private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + private SystemClockType ClockType; + + private DateTime SystemClockContextEpoch; + + private long SystemClockTimePoint; + + private byte[] SystemClockContextEnding; + + private long TimeOffset; + + public ISystemClock(SystemClockType ClockType) + { + m_Commands = new Dictionary<int, ServiceProcessRequest>() + { + { 0, GetCurrentTime }, + { 1, SetCurrentTime }, + { 2, GetSystemClockContext }, + { 3, SetSystemClockContext } + }; + + this.ClockType = ClockType; + SystemClockContextEpoch = System.Diagnostics.Process.GetCurrentProcess().StartTime; + SystemClockContextEnding = new byte[0x10]; + TimeOffset = 0; + + if (ClockType == SystemClockType.User || + ClockType == SystemClockType.Network) + { + SystemClockContextEpoch = SystemClockContextEpoch.ToUniversalTime(); + } + + SystemClockTimePoint = (long)(SystemClockContextEpoch - Epoch).TotalSeconds; + } + + public long GetCurrentTime(ServiceCtx Context) + { + DateTime CurrentTime = DateTime.Now; + + if (ClockType == SystemClockType.User || + ClockType == SystemClockType.Network) + { + CurrentTime = CurrentTime.ToUniversalTime(); + } + + Context.ResponseData.Write((long)((CurrentTime - Epoch).TotalSeconds) + TimeOffset); + + return 0; + } + + public long SetCurrentTime(ServiceCtx Context) + { + DateTime CurrentTime = DateTime.Now; + + if (ClockType == SystemClockType.User || + ClockType == SystemClockType.Network) + { + CurrentTime = CurrentTime.ToUniversalTime(); + } + + TimeOffset = (Context.RequestData.ReadInt64() - (long)(CurrentTime - Epoch).TotalSeconds); + + return 0; + } + + public long GetSystemClockContext(ServiceCtx Context) + { + Context.ResponseData.Write((long)(SystemClockContextEpoch - Epoch).TotalSeconds); + + // The point in time, TODO: is there a link between epoch and this? + Context.ResponseData.Write(SystemClockTimePoint); + + // This seems to be some kind of identifier? + for (int i = 0; i < 0x10; i++) + { + Context.ResponseData.Write(SystemClockContextEnding[i]); + } + + return 0; + } + + public long SetSystemClockContext(ServiceCtx Context) + { + long NewSystemClockEpoch = Context.RequestData.ReadInt64(); + long NewSystemClockTimePoint = Context.RequestData.ReadInt64(); + + SystemClockContextEpoch = Epoch.Add(TimeSpan.FromSeconds(NewSystemClockEpoch)); + SystemClockTimePoint = NewSystemClockTimePoint; + SystemClockContextEnding = Context.RequestData.ReadBytes(0x10); + + return 0; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Time/ITimeZoneService.cs b/Ryujinx.HLE/HOS/Services/Time/ITimeZoneService.cs new file mode 100644 index 00000000..6df28659 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/ITimeZoneService.cs @@ -0,0 +1,280 @@ +using Ryujinx.HLE.HOS.Ipc; +using Ryujinx.HLE.Logging; +using System; +using System.Collections.Generic; +using System.Text; + +using static Ryujinx.HLE.HOS.ErrorCode; + +namespace Ryujinx.HLE.HOS.Services.Time +{ + class ITimeZoneService : IpcService + { + private Dictionary<int, ServiceProcessRequest> m_Commands; + + public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands; + + private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + private TimeZoneInfo TimeZone = TimeZoneInfo.Local; + + public ITimeZoneService() + { + m_Commands = new Dictionary<int, ServiceProcessRequest>() + { + { 0, GetDeviceLocationName }, + { 1, SetDeviceLocationName }, + { 2, GetTotalLocationNameCount }, + { 3, LoadLocationNameList }, + { 4, LoadTimeZoneRule }, + { 100, ToCalendarTime }, + { 101, ToCalendarTimeWithMyRule }, + { 201, ToPosixTime }, + { 202, ToPosixTimeWithMyRule } + }; + } + + public long GetDeviceLocationName(ServiceCtx Context) + { + char[] TzName = TimeZone.Id.ToCharArray(); + + Context.ResponseData.Write(TzName); + + int Padding = 0x24 - TzName.Length; + + for (int Index = 0; Index < Padding; Index++) + { + Context.ResponseData.Write((byte)0); + } + + return 0; + } + + public long SetDeviceLocationName(ServiceCtx Context) + { + byte[] LocationName = Context.RequestData.ReadBytes(0x24); + + string TzID = Encoding.ASCII.GetString(LocationName).TrimEnd('\0'); + + long ResultCode = 0; + + try + { + TimeZone = TimeZoneInfo.FindSystemTimeZoneById(TzID); + } + catch (TimeZoneNotFoundException) + { + ResultCode = MakeError(ErrorModule.Time, 0x3dd); + } + + return ResultCode; + } + + public long GetTotalLocationNameCount(ServiceCtx Context) + { + Context.ResponseData.Write(TimeZoneInfo.GetSystemTimeZones().Count); + + return 0; + } + + public long LoadLocationNameList(ServiceCtx Context) + { + long BufferPosition = Context.Response.SendBuff[0].Position; + long BufferSize = Context.Response.SendBuff[0].Size; + + int Offset = 0; + + foreach (TimeZoneInfo info in TimeZoneInfo.GetSystemTimeZones()) + { + byte[] TzData = Encoding.ASCII.GetBytes(info.Id); + + Context.Memory.WriteBytes(BufferPosition + Offset, TzData); + + int Padding = 0x24 - TzData.Length; + + for (int Index = 0; Index < Padding; Index++) + { + Context.ResponseData.Write((byte)0); + } + + Offset += 0x24; + } + + return 0; + } + + public long LoadTimeZoneRule(ServiceCtx Context) + { + long BufferPosition = Context.Request.ReceiveBuff[0].Position; + long BufferSize = Context.Request.ReceiveBuff[0].Size; + + if (BufferSize != 0x4000) + { + Context.Device.Log.PrintWarning(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{BufferSize:x} (expected 0x4000)"); + } + + long ResultCode = 0; + + byte[] LocationName = Context.RequestData.ReadBytes(0x24); + + string TzID = Encoding.ASCII.GetString(LocationName).TrimEnd('\0'); + + // Check if the Time Zone exists, otherwise error out. + try + { + TimeZoneInfo Info = TimeZoneInfo.FindSystemTimeZoneById(TzID); + + byte[] TzData = Encoding.ASCII.GetBytes(Info.Id); + + // FIXME: This is not in ANY cases accurate, but the games don't care about the content of the buffer, they only pass it. + // TODO: Reverse the TZif2 conversion in PCV to make this match with real hardware. + Context.Memory.WriteBytes(BufferPosition, TzData); + } + catch (TimeZoneNotFoundException) + { + Context.Device.Log.PrintWarning(LogClass.ServiceTime, $"Timezone not found for string: {TzID} (len: {TzID.Length})"); + + ResultCode = MakeError(ErrorModule.Time, 0x3dd); + } + + return ResultCode; + } + + private long ToCalendarTimeWithTz(ServiceCtx Context, long PosixTime, TimeZoneInfo Info) + { + DateTime CurrentTime = Epoch.AddSeconds(PosixTime); + + CurrentTime = TimeZoneInfo.ConvertTimeFromUtc(CurrentTime, Info); + + Context.ResponseData.Write((ushort)CurrentTime.Year); + Context.ResponseData.Write((byte)CurrentTime.Month); + Context.ResponseData.Write((byte)CurrentTime.Day); + Context.ResponseData.Write((byte)CurrentTime.Hour); + Context.ResponseData.Write((byte)CurrentTime.Minute); + Context.ResponseData.Write((byte)CurrentTime.Second); + Context.ResponseData.Write((byte)0); //MilliSecond ? + Context.ResponseData.Write((int)CurrentTime.DayOfWeek); + Context.ResponseData.Write(CurrentTime.DayOfYear - 1); + Context.ResponseData.Write(new byte[8]); //TODO: Find out the names used. + Context.ResponseData.Write((byte)(CurrentTime.IsDaylightSavingTime() ? 1 : 0)); + Context.ResponseData.Write((int)Info.GetUtcOffset(CurrentTime).TotalSeconds); + + return 0; + } + + public long ToCalendarTime(ServiceCtx Context) + { + long PosixTime = Context.RequestData.ReadInt64(); + long BufferPosition = Context.Request.SendBuff[0].Position; + long BufferSize = Context.Request.SendBuff[0].Size; + + if (BufferSize != 0x4000) + { + Context.Device.Log.PrintWarning(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{BufferSize:x} (expected 0x4000)"); + } + + // TODO: Reverse the TZif2 conversion in PCV to make this match with real hardware. + byte[] TzData = Context.Memory.ReadBytes(BufferPosition, 0x24); + + string TzID = Encoding.ASCII.GetString(TzData).TrimEnd('\0'); + + long ResultCode = 0; + + // Check if the Time Zone exists, otherwise error out. + try + { + TimeZoneInfo Info = TimeZoneInfo.FindSystemTimeZoneById(TzID); + + ResultCode = ToCalendarTimeWithTz(Context, PosixTime, Info); + } + catch (TimeZoneNotFoundException) + { + Context.Device.Log.PrintWarning(LogClass.ServiceTime, $"Timezone not found for string: {TzID} (len: {TzID.Length})"); + + ResultCode = MakeError(ErrorModule.Time, 0x3dd); + } + + return ResultCode; + } + + public long ToCalendarTimeWithMyRule(ServiceCtx Context) + { + long PosixTime = Context.RequestData.ReadInt64(); + + return ToCalendarTimeWithTz(Context, PosixTime, TimeZone); + } + + public long ToPosixTime(ServiceCtx Context) + { + long BufferPosition = Context.Request.SendBuff[0].Position; + long BufferSize = Context.Request.SendBuff[0].Size; + + ushort Year = Context.RequestData.ReadUInt16(); + byte Month = Context.RequestData.ReadByte(); + byte Day = Context.RequestData.ReadByte(); + byte Hour = Context.RequestData.ReadByte(); + byte Minute = Context.RequestData.ReadByte(); + byte Second = Context.RequestData.ReadByte(); + + DateTime CalendarTime = new DateTime(Year, Month, Day, Hour, Minute, Second); + + if (BufferSize != 0x4000) + { + Context.Device.Log.PrintWarning(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{BufferSize:x} (expected 0x4000)"); + } + + // TODO: Reverse the TZif2 conversion in PCV to make this match with real hardware. + byte[] TzData = Context.Memory.ReadBytes(BufferPosition, 0x24); + + string TzID = Encoding.ASCII.GetString(TzData).TrimEnd('\0'); + + long ResultCode = 0; + + // Check if the Time Zone exists, otherwise error out. + try + { + TimeZoneInfo Info = TimeZoneInfo.FindSystemTimeZoneById(TzID); + + return ToPosixTimeWithTz(Context, CalendarTime, Info); + } + catch (TimeZoneNotFoundException) + { + Context.Device.Log.PrintWarning(LogClass.ServiceTime, $"Timezone not found for string: {TzID} (len: {TzID.Length})"); + + ResultCode = MakeError(ErrorModule.Time, 0x3dd); + } + + return ResultCode; + } + + public long ToPosixTimeWithMyRule(ServiceCtx Context) + { + ushort Year = Context.RequestData.ReadUInt16(); + byte Month = Context.RequestData.ReadByte(); + byte Day = Context.RequestData.ReadByte(); + byte Hour = Context.RequestData.ReadByte(); + byte Minute = Context.RequestData.ReadByte(); + byte Second = Context.RequestData.ReadByte(); + + DateTime CalendarTime = new DateTime(Year, Month, Day, Hour, Minute, Second, DateTimeKind.Local); + + return ToPosixTimeWithTz(Context, CalendarTime, TimeZone); + } + + private long ToPosixTimeWithTz(ServiceCtx Context, DateTime CalendarTime, TimeZoneInfo Info) + { + DateTime CalenderTimeUTC = TimeZoneInfo.ConvertTimeToUtc(CalendarTime, Info); + + long PosixTime = ((DateTimeOffset)CalenderTimeUTC).ToUnixTimeSeconds(); + + long Position = Context.Request.RecvListBuff[0].Position; + long Size = Context.Request.RecvListBuff[0].Size; + + Context.Memory.WriteInt64(Position, PosixTime); + + Context.ResponseData.Write(1); + + return 0; + } + } +} diff --git a/Ryujinx.HLE/HOS/Services/Time/SystemClockType.cs b/Ryujinx.HLE/HOS/Services/Time/SystemClockType.cs new file mode 100644 index 00000000..54b7df3f --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/SystemClockType.cs @@ -0,0 +1,10 @@ +namespace Ryujinx.HLE.HOS.Services.Time +{ + enum SystemClockType + { + User, + Network, + Local, + EphemeralNetwork + } +}
\ No newline at end of file |
