diff options
| author | Ac_K <Acoustik666@gmail.com> | 2019-09-19 02:45:11 +0200 |
|---|---|---|
| committer | jduncanator <1518948+jduncanator@users.noreply.github.com> | 2019-09-19 10:45:11 +1000 |
| commit | a0720b5681852f3d786d77bd3793b0359dea321c (patch) | |
| tree | 9d8f61e540d1d1d827999902dad95e5c0c1e076e /Ryujinx.HLE/HOS/Services/Time/StaticService | |
| parent | 4af3101b22e6957d6aa48a2768566d658699f4ed (diff) | |
Refactoring HOS folder structure (#771)
* Refactoring HOS folder structure
Refactoring HOS folder structure:
- Added some subfolders when needed (Following structure decided in private).
- Added some `Types` folders when needed.
- Little cleanup here and there.
- Add services placeholders for every HOS services (close #766 and #753).
* Remove Types namespaces
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Time/StaticService')
3 files changed, 416 insertions, 0 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Time/StaticService/ISteadyClock.cs b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISteadyClock.cs new file mode 100644 index 00000000..31f119df --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISteadyClock.cs @@ -0,0 +1,91 @@ +using Ryujinx.Common; +using Ryujinx.HLE.HOS.Services.Time.Clock; + +namespace Ryujinx.HLE.HOS.Services.Time.StaticService +{ + class ISteadyClock : IpcService + { + [Command(0)] + // GetCurrentTimePoint() -> nn::time::SteadyClockTimePoint + public ResultCode GetCurrentTimePoint(ServiceCtx context) + { + SteadyClockTimePoint currentTimePoint = StandardSteadyClockCore.Instance.GetCurrentTimePoint(context.Thread); + + context.ResponseData.WriteStruct(currentTimePoint); + + return ResultCode.Success; + } + + [Command(1)] + // GetTestOffset() -> nn::TimeSpanType + public ResultCode GetTestOffset(ServiceCtx context) + { + context.ResponseData.WriteStruct(StandardSteadyClockCore.Instance.GetTestOffset()); + + return ResultCode.Success; + } + + [Command(2)] + // SetTestOffset(nn::TimeSpanType) + public ResultCode SetTestOffset(ServiceCtx context) + { + TimeSpanType testOffset = context.RequestData.ReadStruct<TimeSpanType>(); + + StandardSteadyClockCore.Instance.SetTestOffset(testOffset); + + return 0; + } + + [Command(100)] // 2.0.0+ + // GetRtcValue() -> u64 + public ResultCode GetRtcValue(ServiceCtx context) + { + ResultCode result = StandardSteadyClockCore.Instance.GetRtcValue(out ulong rtcValue); + + if (result == ResultCode.Success) + { + context.ResponseData.Write(rtcValue); + } + + return result; + } + + [Command(101)] // 2.0.0+ + // IsRtcResetDetected() -> bool + public ResultCode IsRtcResetDetected(ServiceCtx context) + { + context.ResponseData.Write(StandardSteadyClockCore.Instance.IsRtcResetDetected()); + + return ResultCode.Success; + } + + [Command(102)] // 2.0.0+ + // GetSetupResultValue() -> u32 + public ResultCode GetSetupResultValue(ServiceCtx context) + { + context.ResponseData.Write((uint)StandardSteadyClockCore.Instance.GetSetupResultValue()); + + return ResultCode.Success; + } + + [Command(200)] // 3.0.0+ + // GetInternalOffset() -> nn::TimeSpanType + public ResultCode GetInternalOffset(ServiceCtx context) + { + context.ResponseData.WriteStruct(StandardSteadyClockCore.Instance.GetInternalOffset()); + + return ResultCode.Success; + } + + [Command(201)] // 3.0.0-3.0.2 + // SetInternalOffset(nn::TimeSpanType) + public ResultCode SetInternalOffset(ServiceCtx context) + { + TimeSpanType internalOffset = context.RequestData.ReadStruct<TimeSpanType>(); + + StandardSteadyClockCore.Instance.SetInternalOffset(internalOffset); + + return ResultCode.Success; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs new file mode 100644 index 00000000..0d866177 --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/StaticService/ISystemClock.cs @@ -0,0 +1,107 @@ +using Ryujinx.Common; +using Ryujinx.HLE.HOS.Services.Time.Clock; + +namespace Ryujinx.HLE.HOS.Services.Time.StaticService +{ + class ISystemClock : IpcService + { + private SystemClockCore _clockCore; + private bool _writePermission; + + public ISystemClock(SystemClockCore clockCore, bool writePermission) + { + _clockCore = clockCore; + _writePermission = writePermission; + } + + [Command(0)] + // GetCurrentTime() -> nn::time::PosixTime + public ResultCode GetCurrentTime(ServiceCtx context) + { + SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore(); + SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread); + + ResultCode result = _clockCore.GetSystemClockContext(context.Thread, out SystemClockContext clockContext); + + if (result == ResultCode.Success) + { + result = ResultCode.TimeMismatch; + + if (currentTimePoint.ClockSourceId == clockContext.SteadyTimePoint.ClockSourceId) + { + long posixTime = clockContext.Offset + currentTimePoint.TimePoint; + + context.ResponseData.Write(posixTime); + + result = 0; + } + } + + return result; + } + + [Command(1)] + // SetCurrentTime(nn::time::PosixTime) + public ResultCode SetCurrentTime(ServiceCtx context) + { + if (!_writePermission) + { + return ResultCode.PermissionDenied; + } + + long posixTime = context.RequestData.ReadInt64(); + SteadyClockCore steadyClockCore = _clockCore.GetSteadyClockCore(); + SteadyClockTimePoint currentTimePoint = steadyClockCore.GetCurrentTimePoint(context.Thread); + + SystemClockContext clockContext = new SystemClockContext() + { + Offset = posixTime - currentTimePoint.TimePoint, + SteadyTimePoint = currentTimePoint + }; + + ResultCode result = _clockCore.SetSystemClockContext(clockContext); + + if (result == ResultCode.Success) + { + result = _clockCore.Flush(clockContext); + } + + return result; + } + + [Command(2)] + // GetSystemClockContext() -> nn::time::SystemClockContext + public ResultCode GetSystemClockContext(ServiceCtx context) + { + ResultCode result = _clockCore.GetSystemClockContext(context.Thread, out SystemClockContext clockContext); + + if (result == ResultCode.Success) + { + context.ResponseData.WriteStruct(clockContext); + } + + return result; + } + + [Command(3)] + // SetSystemClockContext(nn::time::SystemClockContext) + public ResultCode SetSystemClockContext(ServiceCtx context) + { + if (!_writePermission) + { + return ResultCode.PermissionDenied; + } + + SystemClockContext clockContext = context.RequestData.ReadStruct<SystemClockContext>(); + + ResultCode result = _clockCore.SetSystemClockContext(clockContext); + + if (result == ResultCode.Success) + { + result = _clockCore.Flush(clockContext); + } + + return result; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneService.cs b/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneService.cs new file mode 100644 index 00000000..c65107df --- /dev/null +++ b/Ryujinx.HLE/HOS/Services/Time/StaticService/ITimeZoneService.cs @@ -0,0 +1,218 @@ +using ARMeilleure.Memory; +using Ryujinx.Common; +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Services.Time.TimeZone; +using System; +using System.Text; + +namespace Ryujinx.HLE.HOS.Services.Time.StaticService +{ + class ITimeZoneService : IpcService + { + public ITimeZoneService() { } + + [Command(0)] + // GetDeviceLocationName() -> nn::time::LocationName + public ResultCode GetDeviceLocationName(ServiceCtx context) + { + char[] tzName = TimeZoneManager.Instance.GetDeviceLocationName().ToCharArray(); + + int padding = 0x24 - tzName.Length; + + if (padding < 0) + { + return ResultCode.LocationNameTooLong; + } + + context.ResponseData.Write(tzName); + + for (int index = 0; index < padding; index++) + { + context.ResponseData.Write((byte)0); + } + + return ResultCode.Success; + } + + [Command(1)] + // SetDeviceLocationName(nn::time::LocationName) + public ResultCode SetDeviceLocationName(ServiceCtx context) + { + string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0'); + + return TimeZoneManager.Instance.SetDeviceLocationName(locationName); + } + + [Command(2)] + // GetTotalLocationNameCount() -> u32 + public ResultCode GetTotalLocationNameCount(ServiceCtx context) + { + context.ResponseData.Write(TimeZoneManager.Instance.GetTotalLocationNameCount()); + + return ResultCode.Success; + } + + [Command(3)] + // LoadLocationNameList(u32 index) -> (u32 outCount, buffer<nn::time::LocationName, 6>) + public ResultCode LoadLocationNameList(ServiceCtx context) + { + uint index = context.RequestData.ReadUInt32(); + long bufferPosition = context.Request.ReceiveBuff[0].Position; + long bufferSize = context.Request.ReceiveBuff[0].Size; + + ResultCode errorCode = TimeZoneManager.Instance.LoadLocationNameList(index, out string[] locationNameArray, (uint)bufferSize / 0x24); + + if (errorCode == 0) + { + uint offset = 0; + + foreach (string locationName in locationNameArray) + { + int padding = 0x24 - locationName.Length; + + if (padding < 0) + { + return ResultCode.LocationNameTooLong; + } + + context.Memory.WriteBytes(bufferPosition + offset, Encoding.ASCII.GetBytes(locationName)); + MemoryHelper.FillWithZeros(context.Memory, bufferPosition + offset + locationName.Length, padding); + + offset += 0x24; + } + + context.ResponseData.Write((uint)locationNameArray.Length); + } + + return errorCode; + } + + [Command(4)] + // LoadTimeZoneRule(nn::time::LocationName locationName) -> buffer<nn::time::TimeZoneRule, 0x16> + public ResultCode LoadTimeZoneRule(ServiceCtx context) + { + long bufferPosition = context.Request.ReceiveBuff[0].Position; + long bufferSize = context.Request.ReceiveBuff[0].Size; + + if (bufferSize != 0x4000) + { + // TODO: find error code here + Logger.PrintError(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{bufferSize:x} (expected 0x4000)"); + + throw new InvalidOperationException(); + } + + + string locationName = Encoding.ASCII.GetString(context.RequestData.ReadBytes(0x24)).TrimEnd('\0'); + + ResultCode resultCode = TimeZoneManager.Instance.LoadTimeZoneRules(out TimeZoneRule rules, locationName); + + // Write TimeZoneRule if success + if (resultCode == 0) + { + MemoryHelper.Write(context.Memory, bufferPosition, rules); + } + + return resultCode; + } + + [Command(100)] + // ToCalendarTime(nn::time::PosixTime time, buffer<nn::time::TimeZoneRule, 0x15> rules) -> (nn::time::CalendarTime, nn::time::sf::CalendarAdditionalInfo) + public ResultCode 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) + { + // TODO: find error code here + Logger.PrintError(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{bufferSize:x} (expected 0x4000)"); + + throw new InvalidOperationException(); + } + + TimeZoneRule rules = MemoryHelper.Read<TimeZoneRule>(context.Memory, bufferPosition); + + ResultCode resultCode = TimeZoneManager.ToCalendarTime(rules, posixTime, out CalendarInfo calendar); + + if (resultCode == 0) + { + context.ResponseData.WriteStruct(calendar); + } + + return resultCode; + } + + [Command(101)] + // ToCalendarTimeWithMyRule(nn::time::PosixTime) -> (nn::time::CalendarTime, nn::time::sf::CalendarAdditionalInfo) + public ResultCode ToCalendarTimeWithMyRule(ServiceCtx context) + { + long posixTime = context.RequestData.ReadInt64(); + + ResultCode resultCode = TimeZoneManager.Instance.ToCalendarTimeWithMyRules(posixTime, out CalendarInfo calendar); + + if (resultCode == 0) + { + context.ResponseData.WriteStruct(calendar); + } + + return resultCode; + } + + [Command(201)] + // ToPosixTime(nn::time::CalendarTime calendarTime, buffer<nn::time::TimeZoneRule, 0x15> rules) -> (u32 outCount, buffer<nn::time::PosixTime, 0xa>) + public ResultCode ToPosixTime(ServiceCtx context) + { + long inBufferPosition = context.Request.SendBuff[0].Position; + long inBufferSize = context.Request.SendBuff[0].Size; + + CalendarTime calendarTime = context.RequestData.ReadStruct<CalendarTime>(); + + if (inBufferSize != 0x4000) + { + // TODO: find error code here + Logger.PrintError(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{inBufferSize:x} (expected 0x4000)"); + + throw new InvalidOperationException(); + } + + TimeZoneRule rules = MemoryHelper.Read<TimeZoneRule>(context.Memory, inBufferPosition); + + ResultCode resultCode = TimeZoneManager.ToPosixTime(rules, calendarTime, out long posixTime); + + if (resultCode == 0) + { + long outBufferPosition = context.Request.RecvListBuff[0].Position; + long outBufferSize = context.Request.RecvListBuff[0].Size; + + context.Memory.WriteInt64(outBufferPosition, posixTime); + context.ResponseData.Write(1); + } + + return resultCode; + } + + [Command(202)] + // ToPosixTimeWithMyRule(nn::time::CalendarTime calendarTime) -> (u32 outCount, buffer<nn::time::PosixTime, 0xa>) + public ResultCode ToPosixTimeWithMyRule(ServiceCtx context) + { + CalendarTime calendarTime = context.RequestData.ReadStruct<CalendarTime>(); + + ResultCode resultCode = TimeZoneManager.Instance.ToPosixTimeWithMyRules(calendarTime, out long posixTime); + + if (resultCode == 0) + { + long outBufferPosition = context.Request.RecvListBuff[0].Position; + long outBufferSize = context.Request.RecvListBuff[0].Size; + + context.Memory.WriteInt64(outBufferPosition, posixTime); + + // There could be only one result on one calendar as leap seconds aren't supported. + context.ResponseData.Write(1); + } + + return resultCode; + } + } +}
\ No newline at end of file |
