ISystemSettingsServer.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. using LibHac;
  2. using LibHac.IO;
  3. using Ryujinx.Common.Logging;
  4. using Ryujinx.HLE.FileSystem;
  5. using Ryujinx.HLE.HOS.Ipc;
  6. using Ryujinx.HLE.HOS.SystemState;
  7. using System;
  8. using System.Collections.Generic;
  9. using System.IO;
  10. using System.Text;
  11. namespace Ryujinx.HLE.HOS.Services.Set
  12. {
  13. class ISystemSettingsServer : IpcService
  14. {
  15. private Dictionary<int, ServiceProcessRequest> _commands;
  16. public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => _commands;
  17. public ISystemSettingsServer()
  18. {
  19. _commands = new Dictionary<int, ServiceProcessRequest>
  20. {
  21. { 3, GetFirmwareVersion },
  22. { 4, GetFirmwareVersion2 },
  23. { 23, GetColorSetId },
  24. { 24, SetColorSetId },
  25. { 38, GetSettingsItemValue }
  26. };
  27. }
  28. // GetFirmwareVersion() -> buffer<nn::settings::system::FirmwareVersion, 0x1a, 0x100>
  29. public static long GetFirmwareVersion(ServiceCtx context)
  30. {
  31. return GetFirmwareVersion2(context);
  32. }
  33. // GetFirmwareVersion2() -> buffer<nn::settings::system::FirmwareVersion, 0x1a, 0x100>
  34. public static long GetFirmwareVersion2(ServiceCtx context)
  35. {
  36. long replyPos = context.Request.RecvListBuff[0].Position;
  37. long replySize = context.Request.RecvListBuff[0].Size;
  38. byte[] firmwareData = GetFirmwareData(context.Device);
  39. if (firmwareData != null)
  40. {
  41. context.Memory.WriteBytes(replyPos, firmwareData);
  42. return 0;
  43. }
  44. const byte majorFwVersion = 0x03;
  45. const byte minorFwVersion = 0x00;
  46. const byte microFwVersion = 0x00;
  47. const byte unknown = 0x00; //Build?
  48. const int revisionNumber = 0x0A;
  49. const string platform = "NX";
  50. const string unknownHex = "7fbde2b0bba4d14107bf836e4643043d9f6c8e47";
  51. const string version = "3.0.0";
  52. const string build = "NintendoSDK Firmware for NX 3.0.0-10.0";
  53. //http://switchbrew.org/index.php?title=System_Version_Title
  54. using (MemoryStream ms = new MemoryStream(0x100))
  55. {
  56. BinaryWriter writer = new BinaryWriter(ms);
  57. writer.Write(majorFwVersion);
  58. writer.Write(minorFwVersion);
  59. writer.Write(microFwVersion);
  60. writer.Write(unknown);
  61. writer.Write(revisionNumber);
  62. writer.Write(Encoding.ASCII.GetBytes(platform));
  63. ms.Seek(0x28, SeekOrigin.Begin);
  64. writer.Write(Encoding.ASCII.GetBytes(unknownHex));
  65. ms.Seek(0x68, SeekOrigin.Begin);
  66. writer.Write(Encoding.ASCII.GetBytes(version));
  67. ms.Seek(0x80, SeekOrigin.Begin);
  68. writer.Write(Encoding.ASCII.GetBytes(build));
  69. context.Memory.WriteBytes(replyPos, ms.ToArray());
  70. }
  71. return 0;
  72. }
  73. // GetColorSetId() -> i32
  74. public static long GetColorSetId(ServiceCtx context)
  75. {
  76. context.ResponseData.Write((int)context.Device.System.State.ThemeColor);
  77. return 0;
  78. }
  79. // GetColorSetId() -> i32
  80. public static long SetColorSetId(ServiceCtx context)
  81. {
  82. int colorSetId = context.RequestData.ReadInt32();
  83. context.Device.System.State.ThemeColor = (ColorSet)colorSetId;
  84. return 0;
  85. }
  86. // GetSettingsItemValue(buffer<nn::settings::SettingsName, 0x19, 0x48>, buffer<nn::settings::SettingsItemKey, 0x19, 0x48>) -> (u64, buffer<unknown, 6, 0>)
  87. public static long GetSettingsItemValue(ServiceCtx context)
  88. {
  89. long classPos = context.Request.PtrBuff[0].Position;
  90. long classSize = context.Request.PtrBuff[0].Size;
  91. long namePos = context.Request.PtrBuff[1].Position;
  92. long nameSize = context.Request.PtrBuff[1].Size;
  93. long replyPos = context.Request.ReceiveBuff[0].Position;
  94. long replySize = context.Request.ReceiveBuff[0].Size;
  95. byte[] Class = context.Memory.ReadBytes(classPos, classSize);
  96. byte[] name = context.Memory.ReadBytes(namePos, nameSize);
  97. string askedSetting = Encoding.ASCII.GetString(Class).Trim('\0') + "!" + Encoding.ASCII.GetString(name).Trim('\0');
  98. NxSettings.Settings.TryGetValue(askedSetting, out object nxSetting);
  99. if (nxSetting != null)
  100. {
  101. byte[] settingBuffer = new byte[replySize];
  102. if (nxSetting is string stringValue)
  103. {
  104. if (stringValue.Length + 1 > replySize)
  105. {
  106. Logger.PrintError(LogClass.ServiceSet, $"{askedSetting} String value size is too big!");
  107. }
  108. else
  109. {
  110. settingBuffer = Encoding.ASCII.GetBytes(stringValue + "\0");
  111. }
  112. }
  113. if (nxSetting is int intValue)
  114. {
  115. settingBuffer = BitConverter.GetBytes(intValue);
  116. }
  117. else if (nxSetting is bool boolValue)
  118. {
  119. settingBuffer[0] = boolValue ? (byte)1 : (byte)0;
  120. }
  121. else
  122. {
  123. throw new NotImplementedException(nxSetting.GetType().Name);
  124. }
  125. context.Memory.WriteBytes(replyPos, settingBuffer);
  126. Logger.PrintDebug(LogClass.ServiceSet, $"{askedSetting} set value: {nxSetting} as {nxSetting.GetType()}");
  127. }
  128. else
  129. {
  130. Logger.PrintError(LogClass.ServiceSet, $"{askedSetting} not found!");
  131. }
  132. return 0;
  133. }
  134. public static byte[] GetFirmwareData(Switch device)
  135. {
  136. long titleId = 0x0100000000000809;
  137. string contentPath = device.System.ContentManager.GetInstalledContentPath(titleId, StorageId.NandSystem, ContentType.Data);
  138. if(string.IsNullOrWhiteSpace(contentPath))
  139. {
  140. return null;
  141. }
  142. string firmwareTitlePath = device.FileSystem.SwitchPathToSystemPath(contentPath);
  143. using(FileStream firmwareStream = File.Open(firmwareTitlePath, FileMode.Open, FileAccess.Read))
  144. {
  145. Nca firmwareContent = new Nca(device.System.KeySet, firmwareStream.AsStorage(), false);
  146. IStorage romFsStorage = firmwareContent.OpenSection(0, false, device.System.FsIntegrityCheckLevel, false);
  147. if(romFsStorage == null)
  148. {
  149. return null;
  150. }
  151. Romfs firmwareRomFs = new Romfs(romFsStorage);
  152. IStorage firmwareFile = firmwareRomFs.OpenFile("/file");
  153. byte[] data = new byte[firmwareFile.Length];
  154. firmwareFile.Read(data, 0);
  155. return data;
  156. }
  157. }
  158. }
  159. }