VirtualAmiibo.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. using Ryujinx.Common.Configuration;
  2. using Ryujinx.Common.Memory;
  3. using Ryujinx.HLE.HOS.Services.Mii;
  4. using Ryujinx.HLE.HOS.Services.Mii.Types;
  5. using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
  6. using System;
  7. using System.Collections.Generic;
  8. using System.IO;
  9. using System.Linq;
  10. using System.Text;
  11. using System.Text.Json;
  12. namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
  13. {
  14. static class VirtualAmiibo
  15. {
  16. private static uint _openedApplicationAreaId;
  17. public static byte[] GenerateUuid(string amiiboId, bool useRandomUuid)
  18. {
  19. if (useRandomUuid)
  20. {
  21. return GenerateRandomUuid();
  22. }
  23. VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
  24. if (virtualAmiiboFile.TagUuid.Length == 0)
  25. {
  26. virtualAmiiboFile.TagUuid = GenerateRandomUuid();
  27. SaveAmiiboFile(virtualAmiiboFile);
  28. }
  29. return virtualAmiiboFile.TagUuid;
  30. }
  31. private static byte[] GenerateRandomUuid()
  32. {
  33. byte[] uuid = new byte[9];
  34. new Random().NextBytes(uuid);
  35. uuid[3] = (byte)(0x88 ^ uuid[0] ^ uuid[1] ^ uuid[2]);
  36. uuid[8] = (byte)(uuid[3] ^ uuid[4] ^ uuid[5] ^ uuid[6]);
  37. return uuid;
  38. }
  39. public static CommonInfo GetCommonInfo(string amiiboId)
  40. {
  41. VirtualAmiiboFile amiiboFile = LoadAmiiboFile(amiiboId);
  42. return new CommonInfo()
  43. {
  44. LastWriteYear = (ushort)amiiboFile.LastWriteDate.Year,
  45. LastWriteMonth = (byte)amiiboFile.LastWriteDate.Month,
  46. LastWriteDay = (byte)amiiboFile.LastWriteDate.Day,
  47. WriteCounter = amiiboFile.WriteCounter,
  48. Version = 1,
  49. ApplicationAreaSize = AmiiboConstants.ApplicationAreaSize,
  50. Reserved = new Array52<byte>()
  51. };
  52. }
  53. public static RegisterInfo GetRegisterInfo(string amiiboId)
  54. {
  55. VirtualAmiiboFile amiiboFile = LoadAmiiboFile(amiiboId);
  56. UtilityImpl utilityImpl = new UtilityImpl();
  57. CharInfo charInfo = new CharInfo();
  58. charInfo.SetFromStoreData(StoreData.BuildDefault(utilityImpl, 0));
  59. // TODO: Maybe change the "no name" by the player name when user profile will be implemented.
  60. // charInfo.Nickname = Nickname.FromString("Nickname");
  61. RegisterInfo registerInfo = new RegisterInfo()
  62. {
  63. MiiCharInfo = charInfo,
  64. FirstWriteYear = (ushort)amiiboFile.FirstWriteDate.Year,
  65. FirstWriteMonth = (byte)amiiboFile.FirstWriteDate.Month,
  66. FirstWriteDay = (byte)amiiboFile.FirstWriteDate.Day,
  67. FontRegion = 0,
  68. Reserved1 = new Array64<byte>(),
  69. Reserved2 = new Array58<byte>()
  70. };
  71. Encoding.ASCII.GetBytes("Ryujinx").CopyTo(registerInfo.Nickname.ToSpan());
  72. return registerInfo;
  73. }
  74. public static bool OpenApplicationArea(string amiiboId, uint applicationAreaId)
  75. {
  76. VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
  77. if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == applicationAreaId))
  78. {
  79. _openedApplicationAreaId = applicationAreaId;
  80. return true;
  81. }
  82. return false;
  83. }
  84. public static byte[] GetApplicationArea(string amiiboId)
  85. {
  86. VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
  87. foreach (VirtualAmiiboApplicationArea applicationArea in virtualAmiiboFile.ApplicationAreas)
  88. {
  89. if (applicationArea.ApplicationAreaId == _openedApplicationAreaId)
  90. {
  91. return applicationArea.ApplicationArea;
  92. }
  93. }
  94. return Array.Empty<byte>();
  95. }
  96. public static bool CreateApplicationArea(string amiiboId, uint applicationAreaId, byte[] applicationAreaData)
  97. {
  98. VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
  99. if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == applicationAreaId))
  100. {
  101. return false;
  102. }
  103. virtualAmiiboFile.ApplicationAreas.Add(new VirtualAmiiboApplicationArea()
  104. {
  105. ApplicationAreaId = applicationAreaId,
  106. ApplicationArea = applicationAreaData
  107. });
  108. SaveAmiiboFile(virtualAmiiboFile);
  109. return true;
  110. }
  111. public static void SetApplicationArea(string amiiboId, byte[] applicationAreaData)
  112. {
  113. VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
  114. if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == _openedApplicationAreaId))
  115. {
  116. for (int i = 0; i < virtualAmiiboFile.ApplicationAreas.Count; i++)
  117. {
  118. if (virtualAmiiboFile.ApplicationAreas[i].ApplicationAreaId == _openedApplicationAreaId)
  119. {
  120. virtualAmiiboFile.ApplicationAreas[i] = new VirtualAmiiboApplicationArea()
  121. {
  122. ApplicationAreaId = _openedApplicationAreaId,
  123. ApplicationArea = applicationAreaData
  124. };
  125. break;
  126. }
  127. }
  128. SaveAmiiboFile(virtualAmiiboFile);
  129. }
  130. }
  131. private static VirtualAmiiboFile LoadAmiiboFile(string amiiboId)
  132. {
  133. Directory.CreateDirectory(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
  134. string filePath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{amiiboId}.json");
  135. VirtualAmiiboFile virtualAmiiboFile;
  136. if (File.Exists(filePath))
  137. {
  138. virtualAmiiboFile = JsonSerializer.Deserialize<VirtualAmiiboFile>(File.ReadAllText(filePath));
  139. }
  140. else
  141. {
  142. virtualAmiiboFile = new VirtualAmiiboFile()
  143. {
  144. FileVersion = 0,
  145. TagUuid = Array.Empty<byte>(),
  146. AmiiboId = amiiboId,
  147. FirstWriteDate = DateTime.Now,
  148. LastWriteDate = DateTime.Now,
  149. WriteCounter = 0,
  150. ApplicationAreas = new List<VirtualAmiiboApplicationArea>()
  151. };
  152. SaveAmiiboFile(virtualAmiiboFile);
  153. }
  154. return virtualAmiiboFile;
  155. }
  156. private static void SaveAmiiboFile(VirtualAmiiboFile virtualAmiiboFile)
  157. {
  158. string filePath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{virtualAmiiboFile.AmiiboId}.json");
  159. File.WriteAllText(filePath, JsonSerializer.Serialize(virtualAmiiboFile));
  160. }
  161. }
  162. }