258 lines
11 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|