ITimeZoneServiceForGlue.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.Cpu;
  3. using Ryujinx.HLE.HOS.Services.Time.TimeZone;
  4. using Ryujinx.HLE.Utilities;
  5. using Ryujinx.Memory;
  6. using System;
  7. using System.Runtime.CompilerServices;
  8. using System.Runtime.InteropServices;
  9. using System.Text;
  10. namespace Ryujinx.HLE.HOS.Services.Time.StaticService
  11. {
  12. class ITimeZoneServiceForGlue : IpcService
  13. {
  14. private TimeZoneContentManager _timeZoneContentManager;
  15. private ITimeZoneServiceForPsc _inner;
  16. private bool _writePermission;
  17. public ITimeZoneServiceForGlue(TimeZoneContentManager timeZoneContentManager, bool writePermission)
  18. {
  19. _timeZoneContentManager = timeZoneContentManager;
  20. _writePermission = writePermission;
  21. _inner = new ITimeZoneServiceForPsc(timeZoneContentManager.Manager, writePermission);
  22. }
  23. [CommandHipc(0)]
  24. // GetDeviceLocationName() -> nn::time::LocationName
  25. public ResultCode GetDeviceLocationName(ServiceCtx context)
  26. {
  27. return _inner.GetDeviceLocationName(context);
  28. }
  29. [CommandHipc(1)]
  30. // SetDeviceLocationName(nn::time::LocationName)
  31. public ResultCode SetDeviceLocationName(ServiceCtx context)
  32. {
  33. if (!_writePermission)
  34. {
  35. return ResultCode.PermissionDenied;
  36. }
  37. string locationName = StringUtils.ReadInlinedAsciiString(context.RequestData, 0x24);
  38. return _timeZoneContentManager.SetDeviceLocationName(locationName);
  39. }
  40. [CommandHipc(2)]
  41. // GetTotalLocationNameCount() -> u32
  42. public ResultCode GetTotalLocationNameCount(ServiceCtx context)
  43. {
  44. return _inner.GetTotalLocationNameCount(context);
  45. }
  46. [CommandHipc(3)]
  47. // LoadLocationNameList(u32 index) -> (u32 outCount, buffer<nn::time::LocationName, 6>)
  48. public ResultCode LoadLocationNameList(ServiceCtx context)
  49. {
  50. uint index = context.RequestData.ReadUInt32();
  51. ulong bufferPosition = context.Request.ReceiveBuff[0].Position;
  52. ulong bufferSize = context.Request.ReceiveBuff[0].Size;
  53. ResultCode errorCode = _timeZoneContentManager.LoadLocationNameList(index, out string[] locationNameArray, (uint)bufferSize / 0x24);
  54. if (errorCode == 0)
  55. {
  56. uint offset = 0;
  57. foreach (string locationName in locationNameArray)
  58. {
  59. int padding = 0x24 - locationName.Length;
  60. if (padding < 0)
  61. {
  62. return ResultCode.LocationNameTooLong;
  63. }
  64. context.Memory.Write(bufferPosition + offset, Encoding.ASCII.GetBytes(locationName));
  65. MemoryHelper.FillWithZeros(context.Memory, bufferPosition + offset + (ulong)locationName.Length, padding);
  66. offset += 0x24;
  67. }
  68. context.ResponseData.Write((uint)locationNameArray.Length);
  69. }
  70. return errorCode;
  71. }
  72. [CommandHipc(4)]
  73. // LoadTimeZoneRule(nn::time::LocationName locationName) -> buffer<nn::time::TimeZoneRule, 0x16>
  74. public ResultCode LoadTimeZoneRule(ServiceCtx context)
  75. {
  76. ulong bufferPosition = context.Request.ReceiveBuff[0].Position;
  77. ulong bufferSize = context.Request.ReceiveBuff[0].Size;
  78. if (bufferSize != 0x4000)
  79. {
  80. // TODO: find error code here
  81. Logger.Error?.Print(LogClass.ServiceTime, $"TimeZoneRule buffer size is 0x{bufferSize:x} (expected 0x4000)");
  82. throw new InvalidOperationException();
  83. }
  84. string locationName = StringUtils.ReadInlinedAsciiString(context.RequestData, 0x24);
  85. using (WritableRegion region = context.Memory.GetWritableRegion(bufferPosition, Unsafe.SizeOf<TimeZoneRule>()))
  86. {
  87. ref TimeZoneRule rules = ref MemoryMarshal.Cast<byte, TimeZoneRule>(region.Memory.Span)[0];
  88. return _timeZoneContentManager.LoadTimeZoneRule(ref rules, locationName);
  89. }
  90. }
  91. [CommandHipc(100)]
  92. // ToCalendarTime(nn::time::PosixTime time, buffer<nn::time::TimeZoneRule, 0x15> rules) -> (nn::time::CalendarTime, nn::time::sf::CalendarAdditionalInfo)
  93. public ResultCode ToCalendarTime(ServiceCtx context)
  94. {
  95. return _inner.ToCalendarTime(context);
  96. }
  97. [CommandHipc(101)]
  98. // ToCalendarTimeWithMyRule(nn::time::PosixTime) -> (nn::time::CalendarTime, nn::time::sf::CalendarAdditionalInfo)
  99. public ResultCode ToCalendarTimeWithMyRule(ServiceCtx context)
  100. {
  101. return _inner.ToCalendarTimeWithMyRule(context);
  102. }
  103. [CommandHipc(201)]
  104. // ToPosixTime(nn::time::CalendarTime calendarTime, buffer<nn::time::TimeZoneRule, 0x15> rules) -> (u32 outCount, buffer<nn::time::PosixTime, 0xa>)
  105. public ResultCode ToPosixTime(ServiceCtx context)
  106. {
  107. return _inner.ToPosixTime(context);
  108. }
  109. [CommandHipc(202)]
  110. // ToPosixTimeWithMyRule(nn::time::CalendarTime calendarTime) -> (u32 outCount, buffer<nn::time::PosixTime, 0xa>)
  111. public ResultCode ToPosixTimeWithMyRule(ServiceCtx context)
  112. {
  113. return _inner.ToPosixTimeWithMyRule(context);
  114. }
  115. }
  116. }