ISettingsServer.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.HOS.SystemState;
  3. using System;
  4. using System.Text;
  5. namespace Ryujinx.HLE.HOS.Services.Settings
  6. {
  7. [Service("set")]
  8. class ISettingsServer : IpcService
  9. {
  10. public ISettingsServer(ServiceCtx context) { }
  11. [CommandHipc(0)]
  12. // GetLanguageCode() -> nn::settings::LanguageCode
  13. public ResultCode GetLanguageCode(ServiceCtx context)
  14. {
  15. context.ResponseData.Write(context.Device.System.State.DesiredLanguageCode);
  16. return ResultCode.Success;
  17. }
  18. [CommandHipc(1)]
  19. // GetAvailableLanguageCodes() -> (u32, buffer<nn::settings::LanguageCode, 0xa>)
  20. public ResultCode GetAvailableLanguageCodes(ServiceCtx context)
  21. {
  22. return GetAvailableLanguagesCodesImpl(
  23. context,
  24. context.Request.RecvListBuff[0].Position,
  25. context.Request.RecvListBuff[0].Size,
  26. 0xF);
  27. }
  28. [CommandHipc(2)] // 4.0.0+
  29. // MakeLanguageCode(nn::settings::Language language_index) -> nn::settings::LanguageCode
  30. public ResultCode MakeLanguageCode(ServiceCtx context)
  31. {
  32. int languageIndex = context.RequestData.ReadInt32();
  33. if ((uint)languageIndex >= (uint)SystemStateMgr.LanguageCodes.Length)
  34. {
  35. return ResultCode.LanguageOutOfRange;
  36. }
  37. context.ResponseData.Write(SystemStateMgr.GetLanguageCode(languageIndex));
  38. return ResultCode.Success;
  39. }
  40. [CommandHipc(3)]
  41. // GetAvailableLanguageCodeCount() -> u32
  42. public ResultCode GetAvailableLanguageCodeCount(ServiceCtx context)
  43. {
  44. context.ResponseData.Write(Math.Min(SystemStateMgr.LanguageCodes.Length, 0xF));
  45. return ResultCode.Success;
  46. }
  47. [CommandHipc(4)]
  48. // GetRegionCode() -> u32 nn::settings::RegionCode
  49. public ResultCode GetRegionCode(ServiceCtx context)
  50. {
  51. // NOTE: Service mount 0x8000000000000050 savedata and read the region code here.
  52. RegionCode regionCode = (RegionCode)context.Device.System.State.DesiredRegionCode;
  53. if (regionCode < RegionCode.Min || regionCode > RegionCode.Max)
  54. {
  55. regionCode = RegionCode.USA;
  56. }
  57. context.ResponseData.Write((uint)regionCode);
  58. return ResultCode.Success;
  59. }
  60. [CommandHipc(5)]
  61. // GetAvailableLanguageCodes2() -> (u32, buffer<nn::settings::LanguageCode, 6>)
  62. public ResultCode GetAvailableLanguageCodes2(ServiceCtx context)
  63. {
  64. return GetAvailableLanguagesCodesImpl(
  65. context,
  66. context.Request.ReceiveBuff[0].Position,
  67. context.Request.ReceiveBuff[0].Size,
  68. SystemStateMgr.LanguageCodes.Length);
  69. }
  70. [CommandHipc(6)]
  71. // GetAvailableLanguageCodeCount2() -> u32
  72. public ResultCode GetAvailableLanguageCodeCount2(ServiceCtx context)
  73. {
  74. context.ResponseData.Write(SystemStateMgr.LanguageCodes.Length);
  75. return ResultCode.Success;
  76. }
  77. [CommandHipc(7)] // 4.0.0+
  78. // GetKeyCodeMap() -> buffer<nn::kpr::KeyCodeMap, 0x16>
  79. public ResultCode GetKeyCodeMap(ServiceCtx context)
  80. {
  81. return GetKeyCodeMapImpl(context, 1);
  82. }
  83. [CommandHipc(8)] // 5.0.0+
  84. // GetQuestFlag() -> bool
  85. public ResultCode GetQuestFlag(ServiceCtx context)
  86. {
  87. context.ResponseData.Write(false);
  88. Logger.Stub?.PrintStub(LogClass.ServiceSet);
  89. return ResultCode.Success;
  90. }
  91. [CommandHipc(9)] // 6.0.0+
  92. // GetKeyCodeMap2() -> buffer<nn::kpr::KeyCodeMap, 0x16>
  93. public ResultCode GetKeyCodeMap2(ServiceCtx context)
  94. {
  95. return GetKeyCodeMapImpl(context, 2);
  96. }
  97. [CommandHipc(11)] // 10.1.0+
  98. // GetDeviceNickName() -> buffer<nn::settings::system::DeviceNickName, 0x16>
  99. public ResultCode GetDeviceNickName(ServiceCtx context)
  100. {
  101. ulong deviceNickNameBufferPosition = context.Request.ReceiveBuff[0].Position;
  102. ulong deviceNickNameBufferSize = context.Request.ReceiveBuff[0].Size;
  103. if (deviceNickNameBufferPosition == 0)
  104. {
  105. return ResultCode.NullDeviceNicknameBuffer;
  106. }
  107. if (deviceNickNameBufferSize != 0x80)
  108. {
  109. Logger.Warning?.Print(LogClass.ServiceSet, "Wrong buffer size");
  110. }
  111. context.Memory.Write(deviceNickNameBufferPosition, Encoding.ASCII.GetBytes(context.Device.System.State.DeviceNickName + '\0'));
  112. return ResultCode.Success;
  113. }
  114. private ResultCode GetKeyCodeMapImpl(ServiceCtx context, int version)
  115. {
  116. if (context.Request.ReceiveBuff[0].Size != 0x1000)
  117. {
  118. Logger.Warning?.Print(LogClass.ServiceSet, "Wrong buffer size");
  119. }
  120. byte[] keyCodeMap;
  121. switch ((KeyboardLayout)context.Device.System.State.DesiredKeyboardLayout)
  122. {
  123. case KeyboardLayout.EnglishUs:
  124. long langCode = context.Device.System.State.DesiredLanguageCode;
  125. if (langCode == 0x736e61482d687a) // Zh-Hans
  126. {
  127. keyCodeMap = KeyCodeMaps.ChineseSimplified;
  128. }
  129. else if (langCode == 0x746e61482d687a) // Zh-Hant
  130. {
  131. keyCodeMap = KeyCodeMaps.ChineseTraditional;
  132. }
  133. else
  134. {
  135. keyCodeMap = KeyCodeMaps.EnglishUk;
  136. }
  137. break;
  138. case KeyboardLayout.EnglishUsInternational:
  139. keyCodeMap = KeyCodeMaps.EnglishUsInternational;
  140. break;
  141. case KeyboardLayout.EnglishUk:
  142. keyCodeMap = KeyCodeMaps.EnglishUk;
  143. break;
  144. case KeyboardLayout.French:
  145. keyCodeMap = KeyCodeMaps.French;
  146. break;
  147. case KeyboardLayout.FrenchCa:
  148. keyCodeMap = KeyCodeMaps.FrenchCa;
  149. break;
  150. case KeyboardLayout.Spanish:
  151. keyCodeMap = KeyCodeMaps.Spanish;
  152. break;
  153. case KeyboardLayout.SpanishLatin:
  154. keyCodeMap = KeyCodeMaps.SpanishLatin;
  155. break;
  156. case KeyboardLayout.German:
  157. keyCodeMap = KeyCodeMaps.German;
  158. break;
  159. case KeyboardLayout.Italian:
  160. keyCodeMap = KeyCodeMaps.Italian;
  161. break;
  162. case KeyboardLayout.Portuguese:
  163. keyCodeMap = KeyCodeMaps.Portuguese;
  164. break;
  165. case KeyboardLayout.Russian:
  166. keyCodeMap = KeyCodeMaps.Russian;
  167. break;
  168. case KeyboardLayout.Korean:
  169. keyCodeMap = KeyCodeMaps.Korean;
  170. break;
  171. case KeyboardLayout.ChineseSimplified:
  172. keyCodeMap = KeyCodeMaps.ChineseSimplified;
  173. break;
  174. case KeyboardLayout.ChineseTraditional:
  175. keyCodeMap = KeyCodeMaps.ChineseTraditional;
  176. break;
  177. default: // KeyboardLayout.Default
  178. keyCodeMap = KeyCodeMaps.Default;
  179. break;
  180. }
  181. context.Memory.Write(context.Request.ReceiveBuff[0].Position, keyCodeMap);
  182. if (version == 1 && context.Device.System.State.DesiredKeyboardLayout == (long)KeyboardLayout.Default)
  183. {
  184. context.Memory.Write(context.Request.ReceiveBuff[0].Position, (byte)0x01);
  185. }
  186. return ResultCode.Success;
  187. }
  188. private ResultCode GetAvailableLanguagesCodesImpl(ServiceCtx context, ulong position, ulong size, int maxSize)
  189. {
  190. int count = (int)(size / 8);
  191. if (count > maxSize)
  192. {
  193. count = maxSize;
  194. }
  195. for (int index = 0; index < count; index++)
  196. {
  197. context.Memory.Write(position, SystemStateMgr.GetLanguageCode(index));
  198. position += 8;
  199. }
  200. context.ResponseData.Write(count);
  201. return ResultCode.Success;
  202. }
  203. }
  204. }