Adds the ability to read and write to amiibo bin files (#348)

This introduces the ability to read and write game data and model
information from an Amiibo dump file (BIN format). Note that this
functionality requires the presence of a key_retail.bin file. For the
option to appear and function in the UI, ensure that the key_retail.bin
file is located in the <RyujinxData>/system folder.
This commit is contained in:
Jacobwasbeast
2024-12-19 22:36:46 -06:00
committed by GitHub
parent ff6628149d
commit 0adaa4cb96
29 changed files with 1855 additions and 916 deletions

View File

@@ -4,6 +4,7 @@ using Ryujinx.Common.Utilities;
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Services.Mii;
using Ryujinx.HLE.HOS.Services.Mii.Types;
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager;
using System;
using System.Collections.Generic;
@@ -14,10 +15,11 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
{
static class VirtualAmiibo
{
private static uint _openedApplicationAreaId;
public static uint OpenedApplicationAreaId;
public static byte[] ApplicationBytes = new byte[0];
public static string InputBin = string.Empty;
public static string NickName = string.Empty;
private static readonly AmiiboJsonSerializerContext _serializerContext = AmiiboJsonSerializerContext.Default;
public static byte[] GenerateUuid(string amiiboId, bool useRandomUuid)
{
if (useRandomUuid)
@@ -69,6 +71,11 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
{
VirtualAmiiboFile amiiboFile = LoadAmiiboFile(amiiboId);
string nickname = amiiboFile.NickName ?? "Ryujinx";
if (NickName != string.Empty)
{
nickname = NickName;
NickName = string.Empty;
}
UtilityImpl utilityImpl = new(tickSource);
CharInfo charInfo = new();
@@ -98,16 +105,26 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
{
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
virtualAmiiboFile.NickName = newNickName;
if (InputBin != string.Empty)
{
AmiiboBinReader.SaveBinFile(InputBin, virtualAmiiboFile.NickName);
return;
}
SaveAmiiboFile(virtualAmiiboFile);
}
public static bool OpenApplicationArea(string amiiboId, uint applicationAreaId)
{
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
if (ApplicationBytes.Length > 0)
{
OpenedApplicationAreaId = applicationAreaId;
return true;
}
if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == applicationAreaId))
{
_openedApplicationAreaId = applicationAreaId;
OpenedApplicationAreaId = applicationAreaId;
return true;
}
@@ -117,11 +134,17 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
public static byte[] GetApplicationArea(string amiiboId)
{
if (ApplicationBytes.Length > 0)
{
byte[] bytes = ApplicationBytes;
ApplicationBytes = new byte[0];
return bytes;
}
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
foreach (VirtualAmiiboApplicationArea applicationArea in virtualAmiiboFile.ApplicationAreas)
{
if (applicationArea.ApplicationAreaId == _openedApplicationAreaId)
if (applicationArea.ApplicationAreaId == OpenedApplicationAreaId)
{
return applicationArea.ApplicationArea;
}
@@ -152,17 +175,22 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
public static void SetApplicationArea(string amiiboId, byte[] applicationAreaData)
{
if (InputBin != string.Empty)
{
AmiiboBinReader.SaveBinFile(InputBin, applicationAreaData);
return;
}
VirtualAmiiboFile virtualAmiiboFile = LoadAmiiboFile(amiiboId);
if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == _openedApplicationAreaId))
if (virtualAmiiboFile.ApplicationAreas.Any(item => item.ApplicationAreaId == OpenedApplicationAreaId))
{
for (int i = 0; i < virtualAmiiboFile.ApplicationAreas.Count; i++)
{
if (virtualAmiiboFile.ApplicationAreas[i].ApplicationAreaId == _openedApplicationAreaId)
if (virtualAmiiboFile.ApplicationAreas[i].ApplicationAreaId == OpenedApplicationAreaId)
{
virtualAmiiboFile.ApplicationAreas[i] = new VirtualAmiiboApplicationArea()
{
ApplicationAreaId = _openedApplicationAreaId,
ApplicationAreaId = OpenedApplicationAreaId,
ApplicationArea = applicationAreaData,
};
@@ -205,10 +233,21 @@ namespace Ryujinx.HLE.HOS.Services.Nfc.Nfp
return virtualAmiiboFile;
}
private static void SaveAmiiboFile(VirtualAmiiboFile virtualAmiiboFile)
public static void SaveAmiiboFile(VirtualAmiiboFile virtualAmiiboFile)
{
string filePath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{virtualAmiiboFile.AmiiboId}.json");
JsonHelper.SerializeToFile(filePath, virtualAmiiboFile, _serializerContext.VirtualAmiiboFile);
}
public static bool SaveFileExists(VirtualAmiiboFile virtualAmiiboFile)
{
if (InputBin != string.Empty)
{
SaveAmiiboFile(virtualAmiiboFile);
return true;
}
return File.Exists(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", $"{virtualAmiiboFile.AmiiboId}.json"));
}
}
}