IApplicationFunctions.cs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. using Ryujinx.Core.Logging;
  2. using Ryujinx.Core.OsHle.Ipc;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. namespace Ryujinx.Core.OsHle.Services.Am
  6. {
  7. class IApplicationFunctions : IpcService
  8. {
  9. private Dictionary<int, ServiceProcessRequest> m_Commands;
  10. public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
  11. public IApplicationFunctions()
  12. {
  13. m_Commands = new Dictionary<int, ServiceProcessRequest>()
  14. {
  15. { 1, PopLaunchParameter },
  16. { 20, EnsureSaveData },
  17. { 21, GetDesiredLanguage },
  18. { 22, SetTerminateResult },
  19. { 23, GetDisplayVersion },
  20. { 40, NotifyRunning }
  21. };
  22. }
  23. private const uint LaunchParamsMagic = 0xc79497ca;
  24. public long PopLaunchParameter(ServiceCtx Context)
  25. {
  26. //Only the first 0x18 bytes of the Data seems to be actually used.
  27. MakeObject(Context, new IStorage(MakeLaunchParams()));
  28. return 0;
  29. }
  30. public long EnsureSaveData(ServiceCtx Context)
  31. {
  32. long UIdLow = Context.RequestData.ReadInt64();
  33. long UIdHigh = Context.RequestData.ReadInt64();
  34. Context.Ns.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
  35. Context.ResponseData.Write(0L);
  36. return 0;
  37. }
  38. public long GetDesiredLanguage(ServiceCtx Context)
  39. {
  40. Context.Ns.Log.PrintStub(LogClass.ServiceAm, "Stubbed.");
  41. //This is an enumerator where each number is a differnet language.
  42. //0 is Japanese and 1 is English, need to figure out the other codes.
  43. Context.ResponseData.Write(1L);
  44. return 0;
  45. }
  46. public long SetTerminateResult(ServiceCtx Context)
  47. {
  48. int ErrorCode = Context.RequestData.ReadInt32();
  49. string Result = GetFormattedErrorCode(ErrorCode);
  50. Context.Ns.Log.PrintInfo(LogClass.ServiceAm, $"Result = 0x{ErrorCode:x8} ({Result}).");
  51. return 0;
  52. }
  53. private string GetFormattedErrorCode(int ErrorCode)
  54. {
  55. int Module = (ErrorCode >> 0) & 0x1ff;
  56. int Description = (ErrorCode >> 9) & 0x1fff;
  57. return $"{(2000 + Module):d4}-{Description:d4}";
  58. }
  59. public long GetDisplayVersion(ServiceCtx Context)
  60. {
  61. //FIXME: Need to check correct version on a switch.
  62. Context.ResponseData.Write(1L);
  63. Context.ResponseData.Write(0L);
  64. return 0;
  65. }
  66. public long NotifyRunning(ServiceCtx Context)
  67. {
  68. Context.ResponseData.Write(1);
  69. return 0;
  70. }
  71. private byte[] MakeLaunchParams()
  72. {
  73. //Size needs to be at least 0x88 bytes otherwise application errors.
  74. using (MemoryStream MS = new MemoryStream())
  75. {
  76. BinaryWriter Writer = new BinaryWriter(MS);
  77. MS.SetLength(0x88);
  78. Writer.Write(LaunchParamsMagic);
  79. Writer.Write(1); //IsAccountSelected? Only lower 8 bits actually used.
  80. Writer.Write(1L); //User Id Low (note: User Id needs to be != 0)
  81. Writer.Write(0L); //User Id High
  82. return MS.ToArray();
  83. }
  84. }
  85. }
  86. }