nfp: Amiibo scanning support (#2006)
* Initial Impl. * You just want me cause I'm next * Fix some logics * Fix close button
This commit is contained in:
parent
2b92c10105
commit
a56423802c
22 changed files with 1830 additions and 144 deletions
205
Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs
Normal file
205
Ryujinx.HLE/HOS/Services/Nfc/Nfp/VirtualAmiibo.cs
Normal file
|
@ -0,0 +1,205 @@
|
|||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Memory;
|
||||
using Ryujinx.HLE.HOS.Services.Mii;
|
||||
using Ryujinx.HLE.HOS.Services.Mii.Types;
|
||||
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.UserManager;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
|
||||
{
|
||||
static class VirtualAmiibo
|
||||
{
|
||||
private static uint _openedApplicationAreaId;
|
||||
|
||||
public static byte[] GenerateUuid(string amiiboId, bool useRandomUuid)
|
||||
{
|
||||
if (useRandomUuid)
|
||||
{
|
||||
return GenerateRandomUuid();
|
||||
}
|
||||
|
||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
||||
if (virtualAmiiboFile.TagUuid.Length == 0)
|
||||
{
|
||||
virtualAmiiboFile.TagUuid = GenerateRandomUuid();
|
||||
|
||||
SaveAmiiboFile(virtualAmiiboFile);
|
||||
}
|
||||
|
||||
return virtualAmiiboFile.TagUuid;
|
||||
}
|
||||
|
||||
private static byte[] GenerateRandomUuid()
|
||||
{
|
||||
byte[] uuid = new byte[9];
|
||||
|
||||
new Random().NextBytes(uuid);
|
||||
|
||||
uuid[3] = (byte)(0x88 ^ uuid[0] ^ uuid[1] ^ uuid[2]);
|
||||
uuid[8] = (byte)(uuid[3] ^ uuid[4] ^ uuid[5] ^ uuid[6]);
|
||||
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public static CommonInfo GetCommonInfo(string amiiboId)
|
||||
{
|
||||
VirtualAmiiboFile amiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
||||
return new CommonInfo()
|
||||
{
|
||||
LastWriteYear = (ushort)amiiboFile.LastWriteDate.Year,
|
||||
LastWriteMonth = (byte)amiiboFile.LastWriteDate.Month,
|
||||
LastWriteDay = (byte)amiiboFile.LastWriteDate.Day,
|
||||
WriteCounter = amiiboFile.WriteCounter,
|
||||
Version = 1,
|
||||
ApplicationAreaSize = AmiiboConstants.ApplicationAreaSize,
|
||||
Reserved = new Array52<byte>()
|
||||
};
|
||||
}
|
||||
|
||||
public static RegisterInfo GetRegisterInfo(string amiiboId)
|
||||
{
|
||||
VirtualAmiiboFile amiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
||||
UtilityImpl utilityImpl = new UtilityImpl();
|
||||
CharInfo charInfo = new CharInfo();
|
||||
|
||||
charInfo.SetFromStoreData(StoreData.BuildDefault(utilityImpl, 0));
|
||||
|
||||
// TODO: Maybe change the "no name" by the player name when user profile will be implemented.
|
||||
// charInfo.Nickname = Nickname.FromString("Nickname");
|
||||
|
||||
RegisterInfo registerInfo = new RegisterInfo()
|
||||
{
|
||||
MiiCharInfo = charInfo,
|
||||
FirstWriteYear = (ushort)amiiboFile.FirstWriteDate.Year,
|
||||
FirstWriteMonth = (byte)amiiboFile.FirstWriteDate.Month,
|
||||
FirstWriteDay = (byte)amiiboFile.FirstWriteDate.Day,
|
||||
FontRegion = 0,
|
||||
Reserved1 = new Array64<byte>(),
|
||||
Reserved2 = new Array58<byte>()
|
||||
};
|
||||
|
||||
Encoding.ASCII.GetBytes("Ryujinx").CopyTo(registerInfo.Nickname.ToSpan());
|
||||
|
||||
return registerInfo;
|
||||
}
|
||||
|
||||
public static bool OpenApplicationArea(string amiiboId, uint applicationAreaId)
|
||||
{
|
||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
||||
if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == applicationAreaId))
|
||||
{
|
||||
_openedApplicationAreaId = applicationAreaId;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static byte[] GetApplicationArea(string amiiboId)
|
||||
{
|
||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
||||
foreach (VirtualAmiiboApplicationArea applicationArea in virtualAmiiboFile.ApplicationAreas)
|
||||
{
|
||||
if (applicationArea.ApplicationAreaId == _openedApplicationAreaId)
|
||||
{
|
||||
return applicationArea.ApplicationArea;
|
||||
}
|
||||
}
|
||||
|
||||
return Array.Empty<byte>();
|
||||
}
|
||||
|
||||
public static bool CreateApplicationArea(string amiiboId, uint applicationAreaId, byte[] applicationAreaData)
|
||||
{
|
||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
||||
if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == applicationAreaId))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtualAmiiboFile.ApplicationAreas.Add(new VirtualAmiiboApplicationArea()
|
||||
{
|
||||
ApplicationAreaId = applicationAreaId,
|
||||
ApplicationArea = applicationAreaData
|
||||
});
|
||||
|
||||
SaveAmiiboFile(virtualAmiiboFile);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void SetApplicationArea(string amiiboId, byte[] applicationAreaData)
|
||||
{
|
||||
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
|
||||
|
||||
if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == _openedApplicationAreaId))
|
||||
{
|
||||
for (int i = 0; i < virtualAmiiboFile.ApplicationAreas.Count; i++)
|
||||
{
|
||||
if (virtualAmiiboFile.ApplicationAreas[i].ApplicationAreaId == _openedApplicationAreaId)
|
||||
{
|
||||
virtualAmiiboFile.ApplicationAreas[i] = new VirtualAmiiboApplicationArea()
|
||||
{
|
||||
ApplicationAreaId = _openedApplicationAreaId,
|
||||
ApplicationArea = applicationAreaData
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SaveAmiiboFile(virtualAmiiboFile);
|
||||
}
|
||||
}
|
||||
|
||||
private static VirtualAmiiboFile LoadAmiiboFile(string amiiboId)
|
||||
{
|
||||
Directory.CreateDirectory(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
|
||||
|
||||
string filePath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{amiiboId}.json");
|
||||
|
||||
VirtualAmiiboFile virtualAmiiboFile;
|
||||
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
virtualAmiiboFile = JsonSerializer.Deserialize<VirtualAmiiboFile>(File.ReadAllText(filePath));
|
||||
}
|
||||
else
|
||||
{
|
||||
virtualAmiiboFile = new VirtualAmiiboFile()
|
||||
{
|
||||
FileVersion = 0,
|
||||
TagUuid = Array.Empty<byte>(),
|
||||
AmiiboId = amiiboId,
|
||||
FirstWriteDate = DateTime.Now,
|
||||
LastWriteDate = DateTime.Now,
|
||||
WriteCounter = 0,
|
||||
ApplicationAreas = new List<VirtualAmiiboApplicationArea>()
|
||||
};
|
||||
|
||||
SaveAmiiboFile(virtualAmiiboFile);
|
||||
}
|
||||
|
||||
return virtualAmiiboFile;
|
||||
}
|
||||
|
||||
private static void SaveAmiiboFile(VirtualAmiiboFile virtualAmiiboFile)
|
||||
{
|
||||
string filePath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{virtualAmiiboFile.AmiiboId}.json");
|
||||
|
||||
File.WriteAllText(filePath, JsonSerializer.Serialize(virtualAmiiboFile));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue