Files
Ryujinx-greemdev/src/Ryujinx.HLE/HOS/Services/Nfc/AmiiboDecryption/CharInfoBin.cs
2024-12-23 19:37:42 -06:00

258 lines
11 KiB
C#

using Ryujinx.HLE.HOS.Services.Mii.Types;
using System;
using System.Text;
namespace Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption
{
internal class CharInfoBin
{
public byte MiiVersion { get; private set; }
public byte[] CreateID { get; private set; }
public bool AllowCopying { get; private set; }
public bool ProfanityFlag { get; private set; }
public int RegionLock { get; private set; }
public int CharacterSet { get; private set; }
public int PageIndex { get; private set; }
public int SlotIndex { get; private set; }
public int DeviceOrigin { get; private set; }
public ulong SystemId { get; private set; }
public uint MiiId { get; private set; }
public string CreatorMac { get; private set; }
public bool IsMale { get; private set; }
public int BirthdayMonth { get; private set; }
public int BirthdayDay { get; private set; }
public int FavoriteColor { get; private set; }
public bool FavoriteMii { get; private set; }
public string MiiName { get; private set; }
public string AuthorName { get; private set; }
public int Width { get; private set; }
public int Height { get; private set; }
public bool DisableSharing { get; private set; }
public int FaceShape { get; private set; }
public int SkinColor { get; private set; }
public int Wrinkles { get; private set; }
public int Makeup { get; private set; }
public int HairStyle { get; private set; }
public int HairColor { get; private set; }
public bool FlipHair { get; private set; }
public int EyeStyle { get; private set; }
public int EyeColor { get; private set; }
public int EyeScale { get; private set; }
public int EyeYScale { get; private set; }
public int EyeRotation { get; private set; }
public int EyeXSpacing { get; private set; }
public int EyeYPosition { get; private set; }
public int EyebrowStyle { get; private set; }
public int EyebrowColor { get; private set; }
public int EyebrowScale { get; private set; }
public int EyebrowYScale { get; private set; }
public int EyebrowRotation { get; private set; }
public int EyebrowXSpacing { get; private set; }
public int EyebrowYPosition { get; private set; }
public int NoseStyle { get; private set; }
public int NoseScale { get; private set; }
public int NoseYPosition { get; private set; }
public int MouthStyle { get; private set; }
public int MouthColor { get; private set; }
public int MouthScale { get; private set; }
public int MouthYScale { get; private set; }
public int MouthYPosition { get; private set; }
public int MustacheStyle { get; private set; }
public int BeardStyle { get; private set; }
public int BeardColor { get; private set; }
public int MustacheScale { get; private set; }
public int MustacheYPosition { get; private set; }
public int GlassesStyle { get; private set; }
public int GlassesColor { get; private set; }
public int GlassesScale { get; private set; }
public int GlassesYPosition { get; private set; }
public bool MoleEnabled { get; private set; }
public int MoleScale { get; private set; }
public int MoleXPosition { get; private set; }
public int MoleYPosition { get; private set; }
public static CharInfoBin Parse(byte[] data)
{
if (data.Length < 0x5C)
throw new ArgumentException("Data too short to parse Mii data.");
var mii = new CharInfoBin();
mii.MiiVersion = data[0x0];
byte flags1 = data[0x1];
mii.AllowCopying = (flags1 & 0x1) != 0;
mii.ProfanityFlag = (flags1 & 0x2) != 0;
mii.RegionLock = (flags1 >> 2) & 0x3;
mii.CharacterSet = (flags1 >> 4) & 0x3;
// add the first 0x10 bytes to the create id
mii.CreateID = data[0x0..0x10];
byte position = data[0x2];
mii.PageIndex = position & 0xF;
mii.SlotIndex = (position >> 4) & 0xF;
byte deviceInfo = data[0x3];
mii.DeviceOrigin = (deviceInfo >> 4) & 0x7;
mii.SystemId = BitConverter.ToUInt64(data, 0x4);
mii.MiiId = BitConverter.ToUInt32(data, 0xC);
mii.CreatorMac = BitConverter.ToString(data, 0x10, 0x6).Replace("-", ":");
ushort flags2 = BitConverter.ToUInt16(data, 0x18);
mii.IsMale = (flags2 & 0x1) == 0;
mii.BirthdayMonth = (flags2 >> 1) & 0xF;
mii.BirthdayDay = (flags2 >> 5) & 0x1F;
mii.FavoriteColor = (flags2 >> 10) & 0xF;
mii.FavoriteMii = (flags2 & 0x4000) != 0;
mii.MiiName = ParseUtf16String(data, 0x1A, 20);
ushort dimensions = BitConverter.ToUInt16(data, 0x2E);
mii.Width = dimensions & 0xFF;
mii.Height = (dimensions >> 8) & 0xFF;
byte flags3 = data[0x30];
mii.DisableSharing = (flags3 & 0x1) != 0;
mii.FaceShape = (flags3 >> 1) & 0xF;
mii.SkinColor = (flags3 >> 5) & 0x7;
byte flags4 = data[0x31];
mii.Wrinkles = flags4 & 0xF;
mii.Makeup = (flags4 >> 4) & 0xF;
mii.HairStyle = data[0x32];
byte hairInfo = data[0x33];
mii.HairColor = hairInfo & 0x7;
mii.FlipHair = (hairInfo & 0x8) != 0;
uint eyeInfo = BitConverter.ToUInt32(data, 0x34);
mii.EyeStyle = (int)(eyeInfo & 0x3F);
mii.EyeColor = (int)((eyeInfo >> 6) & 0x7);
mii.EyeScale = (int)((eyeInfo >> 9) & 0xF);
mii.EyeYScale = (int)((eyeInfo >> 13) & 0x7);
mii.EyeRotation = (int)((eyeInfo >> 16) & 0x1F);
mii.EyeXSpacing = (int)((eyeInfo >> 21) & 0xF);
mii.EyeYPosition = (int)((eyeInfo >> 25) & 0x1F);
uint eyebrowInfo = BitConverter.ToUInt32(data, 0x38);
mii.EyebrowStyle = (int)(eyebrowInfo & 0x1F);
mii.EyebrowColor = (int)((eyebrowInfo >> 5) & 0x7);
mii.EyebrowScale = (int)((eyebrowInfo >> 8) & 0xF);
mii.EyebrowYScale = (int)((eyebrowInfo >> 12) & 0x7);
mii.EyebrowRotation = (int)((eyebrowInfo >> 16) & 0xF);
mii.EyebrowXSpacing = (int)((eyebrowInfo >> 21) & 0xF);
mii.EyebrowYPosition = (int)((eyebrowInfo >> 25) & 0x1F);
ushort noseInfo = BitConverter.ToUInt16(data, 0x3C);
mii.NoseStyle = noseInfo & 0x1F;
mii.NoseScale = (noseInfo >> 5) & 0xF;
mii.NoseYPosition = (noseInfo >> 9) & 0x1F;
ushort mouthInfo = BitConverter.ToUInt16(data, 0x3E);
mii.MouthStyle = mouthInfo & 0x3F;
mii.MouthColor = (mouthInfo >> 6) & 0x7;
mii.MouthScale = (mouthInfo >> 9) & 0xF;
mii.MouthYScale = (mouthInfo >> 13) & 0x7;
ushort miscInfo = BitConverter.ToUInt16(data, 0x40);
mii.MouthYPosition = miscInfo & 0x1F;
mii.MustacheStyle = (miscInfo >> 5) & 0x7;
ushort beardInfo = BitConverter.ToUInt16(data, 0x42);
mii.BeardStyle = beardInfo & 0x7;
mii.BeardColor = (beardInfo >> 3) & 0x7;
ushort mustacheInfo = BitConverter.ToUInt16(data, 0x44);
mii.MustacheScale = mustacheInfo & 0xF;
mii.MustacheYPosition = (mustacheInfo >> 4) & 0x1F;
ushort glassesInfo = BitConverter.ToUInt16(data, 0x46);
mii.GlassesStyle = glassesInfo & 0xF;
mii.GlassesColor = (glassesInfo >> 4) & 0x7;
mii.GlassesScale = (glassesInfo >> 7) & 0xF;
mii.GlassesYPosition = (glassesInfo >> 11) & 0x1F;
byte moleFlags = data[0x48];
mii.MoleEnabled = (moleFlags & 0x1) != 0;
mii.MoleScale = (moleFlags >> 1) & 0xF;
ushort moleInfo = BitConverter.ToUInt16(data, 0x46);
mii.MoleEnabled = (moleInfo & 0x1) != 0;
mii.MoleScale = (moleInfo >> 1) & 0xF; // 4 bits for scale
mii.MoleXPosition = (moleInfo >> 5) & 0x1F; // 5 bits for X position
mii.MoleYPosition = (moleInfo >> 10) & 0x1F; // 5 bits for Y position
return mii;
}
private static string ParseUtf16String(byte[] data, int offset, int maxLength)
{
int length = 0;
for (int i = 0; i < maxLength * 2; i += 2)
{
if (data[offset + i] == 0 && data[offset + i + 1] == 0)
break;
length++;
}
return Encoding.Unicode.GetString(data, offset, length * 2);
}
public CharInfo ConvertToCharInfo(CharInfo Info)
{
//UInt128 CreateId = BitConverter.ToUInt128(CreateID, 0);
//Info.CreateId = new CreateId(CreateId);
Info.Nickname = Nickname.FromString(MiiName);
Info.FavoriteColor = (byte)FavoriteColor;
Info.Gender = IsMale ? Gender.Male : Gender.Female;
Info.Height = (byte)Height;
Info.FacelineType = (FacelineType)FaceShape;
Info.FacelineColor = (FacelineColor)SkinColor;
Info.FacelineWrinkle = (FacelineWrinkle)Wrinkles;
Info.FacelineMake = (FacelineMake)Makeup;
Info.HairType = (HairType)HairStyle;
Info.HairColor = (CommonColor)HairColor;
Info.HairFlip = FlipHair ? HairFlip.Left : HairFlip.Right;
Info.EyeType = (EyeType)EyeStyle;
Info.EyeColor = (CommonColor)EyeColor;
Info.EyeScale = (byte)EyeScale;
Info.EyeAspect = (byte)EyeYScale;
Info.EyeRotate = (byte)EyeRotation;
Info.EyeX = (byte)EyeXSpacing;
Info.EyeY = (byte)EyeYPosition;
Info.EyebrowType = (EyebrowType)EyebrowStyle;
Info.EyebrowColor = (CommonColor)EyebrowColor;
Info.EyebrowScale = (byte)EyebrowScale;
Info.EyebrowAspect = (byte)EyebrowYScale;
Info.EyebrowRotate = (byte)EyebrowRotation;
Info.EyebrowX = (byte)EyebrowXSpacing;
Info.EyebrowY = (byte)EyebrowYPosition;
Info.NoseType = (NoseType)NoseStyle;
Info.NoseScale = (byte)NoseScale;
Info.NoseY = (byte)NoseYPosition;
Info.MouthType = (MouthType)MouthStyle;
Info.MouthColor = (CommonColor)MouthColor;
Info.MouthScale = (byte)MouthScale;
Info.MouthAspect = (byte)MouthYScale;
Info.MouthY = (byte)MouthYPosition;
Info.BeardType = (BeardType)BeardStyle;
Info.BeardColor = (CommonColor)BeardColor;
Info.MustacheType = (MustacheType)MustacheStyle;
Info.MustacheScale = (byte)MustacheScale;
Info.MustacheY = (byte)MustacheYPosition;
Info.GlassType = (GlassType)GlassesStyle;
Info.GlassColor = (CommonColor)GlassesColor;
Info.GlassScale = (byte)GlassesScale;
Info.GlassY = (byte)GlassesYPosition;
Info.MoleType = MoleEnabled ? MoleType.OneDot : MoleType.None;
Info.MoleScale = (byte)MoleScale;
Info.MoleX = (byte)MoleXPosition;
Info.MoleY = (byte)MoleYPosition;
return Info;
}
}
}