-
Notifications
You must be signed in to change notification settings - Fork 444
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This adds the missing Cabinet Applet, which allows for formatting Amiibos and changing their names.
- Loading branch information
1 parent
17483aa
commit 08b7257
Showing
24 changed files
with
335 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
using Ryujinx.Common.Logging; | ||
using Ryujinx.Common.Memory; | ||
using Ryujinx.HLE.HOS.Services.Am.AppletAE; | ||
using Ryujinx.HLE.HOS.Services.Hid.HidServer; | ||
using Ryujinx.HLE.HOS.Services.Hid; | ||
using Ryujinx.HLE.HOS.Services.Nfc.Nfp; | ||
using Ryujinx.HLE.HOS.Services.Nfc.Nfp.NfpManager; | ||
using System; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using System.Text; | ||
|
||
namespace Ryujinx.HLE.HOS.Applets.Cabinet | ||
{ | ||
internal unsafe class CabinetApplet : IApplet | ||
{ | ||
private readonly Horizon _system; | ||
private AppletSession _normalSession; | ||
|
||
public event EventHandler AppletStateChanged; | ||
|
||
public CabinetApplet(Horizon system) | ||
{ | ||
_system = system; | ||
} | ||
|
||
public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession) | ||
{ | ||
_normalSession = normalSession; | ||
|
||
byte[] launchParams = _normalSession.Pop(); | ||
byte[] startParamBytes = _normalSession.Pop(); | ||
|
||
StartParamForAmiiboSettings startParam = IApplet.ReadStruct<StartParamForAmiiboSettings>(startParamBytes); | ||
|
||
Logger.Stub?.PrintStub(LogClass.ServiceAm, $"CabinetApplet Start Type: {startParam.Type}"); | ||
|
||
switch (startParam.Type) | ||
{ | ||
case 0: | ||
StartNicknameAndOwnerSettings(ref startParam); | ||
break; | ||
case 1: | ||
case 3: | ||
StartFormatter(ref startParam); | ||
break; | ||
default: | ||
Logger.Error?.Print(LogClass.ServiceAm, $"Unknown AmiiboSettings type: {startParam.Type}"); | ||
break; | ||
} | ||
|
||
// Prepare the response | ||
ReturnValueForAmiiboSettings returnValue = new() | ||
{ | ||
AmiiboSettingsReturnFlag = (byte)AmiiboSettingsReturnFlag.HasRegisterInfo, | ||
DeviceHandle = new DeviceHandle | ||
{ | ||
Handle = 0 // Dummy device handle | ||
}, | ||
RegisterInfo = startParam.RegisterInfo | ||
}; | ||
|
||
// Push the response | ||
_normalSession.Push(BuildResponse(returnValue)); | ||
AppletStateChanged?.Invoke(this, null); | ||
|
||
_system.ReturnFocus(); | ||
|
||
return ResultCode.Success; | ||
} | ||
|
||
public ResultCode GetResult() | ||
{ | ||
_system.Device.System.NfpDevices.RemoveAt(0); | ||
return ResultCode.Success; | ||
} | ||
|
||
private void StartFormatter(ref StartParamForAmiiboSettings startParam) | ||
{ | ||
// Initialize RegisterInfo | ||
startParam.RegisterInfo = new RegisterInfo(); | ||
} | ||
|
||
private void StartNicknameAndOwnerSettings(ref StartParamForAmiiboSettings startParam) | ||
{ | ||
_system.Device.UIHandler.DisplayCabinetDialog(out string newName); | ||
byte[] nameBytes = Encoding.UTF8.GetBytes(newName); | ||
Array41<byte> nickName = new Array41<byte>(); | ||
nameBytes.CopyTo(nickName.AsSpan()); | ||
startParam.RegisterInfo.Nickname = nickName; | ||
NfpDevice devicePlayer1 = new() | ||
{ | ||
NpadIdType = NpadIdType.Player1, | ||
Handle = HidUtils.GetIndexFromNpadIdType(NpadIdType.Player1), | ||
State = NfpDeviceState.SearchingForTag, | ||
}; | ||
_system.Device.System.NfpDevices.Add(devicePlayer1); | ||
_system.Device.UIHandler.DisplayCabinetMessageDialog(); | ||
string amiiboId = string.Empty; | ||
bool scanned = false; | ||
while (!scanned) | ||
{ | ||
for (int i = 0; i < _system.Device.System.NfpDevices.Count; i++) | ||
{ | ||
if (_system.Device.System.NfpDevices[i].State == NfpDeviceState.TagFound) | ||
{ | ||
amiiboId = _system.Device.System.NfpDevices[i].AmiiboId; | ||
scanned = true; | ||
} | ||
} | ||
} | ||
VirtualAmiibo.UpdateNickName(amiiboId, newName); | ||
} | ||
|
||
private static byte[] BuildResponse(ReturnValueForAmiiboSettings returnValue) | ||
{ | ||
int size = Unsafe.SizeOf<ReturnValueForAmiiboSettings>(); | ||
byte[] bytes = new byte[size]; | ||
|
||
fixed (byte* bytesPtr = bytes) | ||
{ | ||
Unsafe.Write(bytesPtr, returnValue); | ||
} | ||
|
||
return bytes; | ||
} | ||
|
||
public static T ReadStruct<T>(byte[] data) where T : unmanaged | ||
{ | ||
if (data.Length < Unsafe.SizeOf<T>()) | ||
{ | ||
throw new ArgumentException("Not enough data to read the struct"); | ||
} | ||
|
||
fixed (byte* dataPtr = data) | ||
{ | ||
return Unsafe.Read<T>(dataPtr); | ||
} | ||
} | ||
|
||
#region Structs | ||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)] | ||
public unsafe struct TagInfo | ||
{ | ||
public fixed byte Data[0x58]; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)] | ||
public unsafe struct StartParamForAmiiboSettings | ||
{ | ||
public byte ZeroValue; // Left at zero by sdknso | ||
public byte Type; | ||
public byte Flags; | ||
public byte AmiiboSettingsStartParamOffset28; | ||
public ulong AmiiboSettingsStartParam0; | ||
|
||
public TagInfo TagInfo; // Only enabled when flags bit 1 is set | ||
public RegisterInfo RegisterInfo; // Only enabled when flags bit 2 is set | ||
|
||
public fixed byte StartParamExtraData[0x20]; | ||
|
||
public fixed byte Reserved[0x24]; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)] | ||
public unsafe struct ReturnValueForAmiiboSettings | ||
{ | ||
public byte AmiiboSettingsReturnFlag; | ||
private byte Padding1; | ||
private byte Padding2; | ||
private byte Padding3; | ||
public DeviceHandle DeviceHandle; | ||
public TagInfo TagInfo; | ||
public RegisterInfo RegisterInfo; | ||
public fixed byte IgnoredBySdknso[0x24]; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential, Pack = 1)] | ||
public struct DeviceHandle | ||
{ | ||
public ulong Handle; | ||
} | ||
|
||
public enum AmiiboSettingsReturnFlag : byte | ||
{ | ||
Cancel = 0, | ||
HasTagInfo = 2, | ||
HasRegisterInfo = 4, | ||
HasTagInfoAndRegisterInfo = 6 | ||
} | ||
|
||
#endregion | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.