ISettingsServer.cs 7.6 KB

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