From e33430355954c77c05b240e1453a5daaf6202d72 Mon Sep 17 00:00:00 2001
From: Mary <me@thog.eu>
Date: Wed, 23 Jun 2021 22:24:16 +0200
Subject: [PATCH] mii: Fix multiple inconsistencies (#2392)

I found multiple inconsistencies while diffing with latest sdb, this PR fixes those findings.
---
 Ryujinx.HLE/HOS/Services/Mii/Helper.cs        |  9 +++-
 .../HOS/Services/Mii/MiiDatabaseManager.cs    | 52 +++++++++----------
 .../HOS/Services/Mii/Types/CoreData.cs        |  2 +-
 .../Mii/Types/NintendoFigurineDatabase.cs     |  2 +-
 .../HOS/Services/Mii/Types/StoreData.cs       | 19 ++++---
 5 files changed, 44 insertions(+), 40 deletions(-)

diff --git a/Ryujinx.HLE/HOS/Services/Mii/Helper.cs b/Ryujinx.HLE/HOS/Services/Mii/Helper.cs
index ea469ac996..d5fa98ea5c 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/Helper.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/Helper.cs
@@ -6,7 +6,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
 {
     static class Helper
     {
-        public static ushort CalculateCrc16BE(ReadOnlySpan<byte> data, int crc = 0)
+        public static ushort CalculateCrc16(ReadOnlySpan<byte> data, int crc, bool reverseEndianess)
         {
             const ushort poly = 0x1021;
 
@@ -25,7 +25,12 @@ namespace Ryujinx.HLE.HOS.Services.Mii
                 }
             }
 
-            return BinaryPrimitives.ReverseEndianness((ushort)crc);
+            if (reverseEndianess)
+            {
+                return (ushort)(BinaryPrimitives.ReverseEndianness(crc) >> 16);
+            }
+
+            return (ushort)crc;
         }
 
         public static UInt128 GetDeviceId()
diff --git a/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs b/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs
index 0fe6220c6b..4491f2c880 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/MiiDatabaseManager.cs
@@ -416,35 +416,35 @@ namespace Ryujinx.HLE.HOS.Services.Mii
                 return ResultCode.InvalidStoreData;
             }
 
-            if (!metadata.MiiKeyCode.IsEnabledSpecialMii() && !storeData.IsSpecial())
+            if (!metadata.MiiKeyCode.IsEnabledSpecialMii() && storeData.IsSpecial())
             {
-                if (_database.GetIndexByCreatorId(out int index, storeData.CreateId))
-                {
-                    StoreData oldStoreData = _database.Get(index);
-
-                    if (oldStoreData.IsSpecial())
-                    {
-                        return ResultCode.InvalidOperationOnSpecialMii;
-                    }
-
-                    _database.Replace(index, storeData);
-                }
-                else
-                {
-                    if (_database.IsFull())
-                    {
-                        return ResultCode.DatabaseFull;
-                    }
-
-                    _database.Add(storeData);
-                }
-
-                MarkDirty(metadata);
-
-                return ResultCode.Success;
+                return ResultCode.InvalidOperationOnSpecialMii;
             }
 
-            return ResultCode.InvalidOperationOnSpecialMii;
+            if (_database.GetIndexByCreatorId(out int index, storeData.CreateId))
+            {
+                StoreData oldStoreData = _database.Get(index);
+
+                if (oldStoreData.IsSpecial())
+                {
+                    return ResultCode.InvalidOperationOnSpecialMii;
+                }
+
+                _database.Replace(index, storeData);
+            }
+            else
+            {
+                if (_database.IsFull())
+                {
+                    return ResultCode.DatabaseFull;
+                }
+
+                _database.Add(storeData);
+            }
+
+            MarkDirty(metadata);
+
+            return ResultCode.Success;
         }
 
         public ResultCode Delete(DatabaseSessionMetadata metadata, CreateId createId)
diff --git a/Ryujinx.HLE/HOS/Services/Mii/Types/CoreData.cs b/Ryujinx.HLE/HOS/Services/Mii/Types/CoreData.cs
index 39a3945b0e..f3a101d8b4 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/Types/CoreData.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/Types/CoreData.cs
@@ -588,7 +588,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
             Nickname        = charInfo.Nickname;
             FontRegion      = charInfo.FontRegion;
             FavoriteColor   = charInfo.FavoriteColor;
-            Gender          = (Gender)charInfo.Gender;
+            Gender          = charInfo.Gender;
             Height          = charInfo.Height;
             Build           = charInfo.Build;
             Type            = charInfo.Type;
diff --git a/Ryujinx.HLE/HOS/Services/Mii/Types/NintendoFigurineDatabase.cs b/Ryujinx.HLE/HOS/Services/Mii/Types/NintendoFigurineDatabase.cs
index 7e6782f09b..14eda2ed86 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/Types/NintendoFigurineDatabase.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/Types/NintendoFigurineDatabase.cs
@@ -233,7 +233,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
 
         private ushort CalculateCrc()
         {
-            return Helper.CalculateCrc16BE(AsSpanWithoutCrc());
+            return Helper.CalculateCrc16(AsSpanWithoutCrc(), 0, true);
         }
 
         public Span<byte> AsSpan()
diff --git a/Ryujinx.HLE/HOS/Services/Mii/Types/StoreData.cs b/Ryujinx.HLE/HOS/Services/Mii/Types/StoreData.cs
index 7db4ab34b1..6b7e3e5a04 100644
--- a/Ryujinx.HLE/HOS/Services/Mii/Types/StoreData.cs
+++ b/Ryujinx.HLE/HOS/Services/Mii/Types/StoreData.cs
@@ -49,26 +49,30 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
 
         public bool IsValidDataCrc()
         {
-            return DataCrc == CalculateDataCrc();
+            return Helper.CalculateCrc16(AsSpanWithoutDeviceCrc(), 0, false) == 0;
         }
 
         public bool IsValidDeviceCrc()
         {
-            return DeviceCrc == CalculateDeviceCrc();
+            UInt128 deviceId = Helper.GetDeviceId();
+
+            ushort deviceIdCrc16 = Helper.CalculateCrc16(SpanHelpers.AsByteSpan(ref deviceId), 0, false);
+
+            return Helper.CalculateCrc16(AsSpan(), deviceIdCrc16, false) == 0;
         }
 
         private ushort CalculateDataCrc()
         {
-            return Helper.CalculateCrc16BE(AsSpanWithoutCrc());
+            return Helper.CalculateCrc16(AsSpanWithoutDeviceCrc(), 0, true);
         }
 
         private ushort CalculateDeviceCrc()
         {
             UInt128 deviceId = Helper.GetDeviceId();
 
-            ushort deviceIdCrc16 = Helper.CalculateCrc16BE(SpanHelpers.AsByteSpan(ref deviceId));
+            ushort deviceIdCrc16 = Helper.CalculateCrc16(SpanHelpers.AsByteSpan(ref deviceId), 0, false);
 
-            return Helper.CalculateCrc16BE(AsSpanWithoutDeviceCrc(), deviceIdCrc16);
+            return Helper.CalculateCrc16(AsSpan(), deviceIdCrc16, true);
         }
 
         private ReadOnlySpan<byte> AsSpan()
@@ -76,11 +80,6 @@ namespace Ryujinx.HLE.HOS.Services.Mii.Types
             return MemoryMarshal.AsBytes(SpanHelpers.CreateReadOnlySpan(in this, 1));
         }
 
-        private ReadOnlySpan<byte> AsSpanWithoutCrc()
-        {
-            return AsSpan().Slice(0, Size - 4);
-        }
-
         private ReadOnlySpan<byte> AsSpanWithoutDeviceCrc()
         {
             return AsSpan().Slice(0, Size - 2);