aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.HLE/HOS/Services/Mii/DatabaseImpl.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.HLE/HOS/Services/Mii/DatabaseImpl.cs')
-rw-r--r--src/Ryujinx.HLE/HOS/Services/Mii/DatabaseImpl.cs328
1 files changed, 328 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/HOS/Services/Mii/DatabaseImpl.cs b/src/Ryujinx.HLE/HOS/Services/Mii/DatabaseImpl.cs
new file mode 100644
index 00000000..6d65de95
--- /dev/null
+++ b/src/Ryujinx.HLE/HOS/Services/Mii/DatabaseImpl.cs
@@ -0,0 +1,328 @@
+using LibHac;
+using Ryujinx.Cpu;
+using Ryujinx.HLE.HOS.Services.Mii.Types;
+using System;
+
+namespace Ryujinx.HLE.HOS.Services.Mii
+{
+ class DatabaseImpl
+ {
+ private static DatabaseImpl _instance;
+
+ public static DatabaseImpl Instance
+ {
+ get
+ {
+ if (_instance == null)
+ {
+ _instance = new DatabaseImpl();
+ }
+
+ return _instance;
+ }
+ }
+
+ private UtilityImpl _utilityImpl;
+ private MiiDatabaseManager _miiDatabase;
+ private bool _isBroken;
+
+ public DatabaseImpl()
+ {
+ _miiDatabase = new MiiDatabaseManager();
+ }
+
+ public bool IsUpdated(DatabaseSessionMetadata metadata, SourceFlag flag)
+ {
+ if (flag.HasFlag(SourceFlag.Database))
+ {
+ return _miiDatabase.IsUpdated(metadata);
+ }
+
+ return false;
+ }
+
+ public bool IsBrokenDatabaseWithClearFlag()
+ {
+ bool result = _isBroken;
+
+ if (_isBroken)
+ {
+ _isBroken = false;
+
+ Format(new DatabaseSessionMetadata(0, new SpecialMiiKeyCode()));
+ }
+
+ return result;
+ }
+
+ public bool IsFullDatabase()
+ {
+ return _miiDatabase.IsFullDatabase();
+ }
+
+ private ResultCode GetDefault<T>(SourceFlag flag, ref int count, Span<T> elements) where T : struct, IElement
+ {
+ if (!flag.HasFlag(SourceFlag.Default))
+ {
+ return ResultCode.Success;
+ }
+
+ for (uint i = 0; i < DefaultMii.TableLength; i++)
+ {
+ if (count >= elements.Length)
+ {
+ return ResultCode.BufferTooSmall;
+ }
+
+ elements[count] = default;
+ elements[count].SetFromStoreData(StoreData.BuildDefault(_utilityImpl, i));
+ elements[count].SetSource(Source.Default);
+
+ count++;
+ }
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode UpdateLatest<T>(DatabaseSessionMetadata metadata, IStoredData<T> oldMiiData, SourceFlag flag, IStoredData<T> newMiiData) where T : unmanaged
+ {
+ if (!flag.HasFlag(SourceFlag.Database))
+ {
+ return ResultCode.NotFound;
+ }
+
+ if (metadata.IsInterfaceVersionSupported(1) && !oldMiiData.IsValid())
+ {
+ return oldMiiData.InvalidData;
+ }
+
+ ResultCode result = _miiDatabase.FindIndex(metadata, out int index, oldMiiData.CreateId);
+
+ if (result == ResultCode.Success)
+ {
+ _miiDatabase.Get(metadata, index, out StoreData storeData);
+
+ if (storeData.Type != oldMiiData.Type)
+ {
+ return ResultCode.NotFound;
+ }
+
+ newMiiData.SetFromStoreData(storeData);
+
+ if (oldMiiData == newMiiData)
+ {
+ return ResultCode.NotUpdated;
+ }
+ }
+
+ return result;
+ }
+
+ public ResultCode Get<T>(DatabaseSessionMetadata metadata, SourceFlag flag, out int count, Span<T> elements) where T : struct, IElement
+ {
+ count = 0;
+
+ if (!flag.HasFlag(SourceFlag.Database))
+ {
+ return GetDefault(flag, ref count, elements);
+ }
+
+ int databaseCount = _miiDatabase.GetCount(metadata);
+
+ for (int i = 0; i < databaseCount; i++)
+ {
+ if (count >= elements.Length)
+ {
+ return ResultCode.BufferTooSmall;
+ }
+
+ _miiDatabase.Get(metadata, i, out StoreData storeData);
+
+ elements[count] = default;
+ elements[count].SetFromStoreData(storeData);
+ elements[count].SetSource(Source.Database);
+
+ count++;
+ }
+
+ return GetDefault(flag, ref count, elements);
+ }
+
+ public ResultCode InitializeDatabase(ITickSource tickSource, HorizonClient horizonClient)
+ {
+ _utilityImpl = new UtilityImpl(tickSource);
+ _miiDatabase.InitializeDatabase(horizonClient);
+ _miiDatabase.LoadFromFile(out _isBroken);
+
+ // Nintendo ignores any error code from before.
+ return ResultCode.Success;
+ }
+
+ public DatabaseSessionMetadata CreateSessionMetadata(SpecialMiiKeyCode miiKeyCode)
+ {
+ return _miiDatabase.CreateSessionMetadata(miiKeyCode);
+ }
+
+ public void SetInterfaceVersion(DatabaseSessionMetadata metadata, uint interfaceVersion)
+ {
+ _miiDatabase.SetInterfaceVersion(metadata, interfaceVersion);
+ }
+
+ public void Format(DatabaseSessionMetadata metadata)
+ {
+ _miiDatabase.FormatDatabase(metadata);
+ _miiDatabase.SaveDatabase();
+ }
+
+ public ResultCode DestroyFile(DatabaseSessionMetadata metadata)
+ {
+ _isBroken = true;
+
+ return _miiDatabase.DestroyFile(metadata);
+ }
+
+ public void BuildDefault(uint index, out CharInfo charInfo)
+ {
+ StoreData storeData = StoreData.BuildDefault(_utilityImpl, index);
+
+ charInfo = default;
+
+ charInfo.SetFromStoreData(storeData);
+ }
+
+ public void BuildRandom(Age age, Gender gender, Race race, out CharInfo charInfo)
+ {
+ StoreData storeData = StoreData.BuildRandom(_utilityImpl, age, gender, race);
+
+ charInfo = default;
+
+ charInfo.SetFromStoreData(storeData);
+ }
+
+ public ResultCode DeleteFile()
+ {
+ return _miiDatabase.DeleteFile();
+ }
+
+ public ResultCode ConvertCoreDataToCharInfo(CoreData coreData, out CharInfo charInfo)
+ {
+ charInfo = new CharInfo();
+
+ if (!coreData.IsValid())
+ {
+ return ResultCode.InvalidCoreData;
+ }
+
+ StoreData storeData = StoreData.BuildFromCoreData(_utilityImpl, coreData);
+
+ if (!storeData.CoreData.Nickname.IsValidForFontRegion(storeData.CoreData.FontRegion))
+ {
+ storeData.CoreData.Nickname = Nickname.Question;
+ storeData.UpdateCrc();
+ }
+
+ charInfo.SetFromStoreData(storeData);
+
+ return ResultCode.Success;
+ }
+
+ public int FindIndex(CreateId createId, bool isSpecial)
+ {
+ if (_miiDatabase.FindIndex(out int index, createId, isSpecial) == ResultCode.Success)
+ {
+ return index;
+ }
+
+ return -1;
+ }
+
+ public uint GetCount(DatabaseSessionMetadata metadata, SourceFlag flag)
+ {
+ int count = 0;
+
+ if (flag.HasFlag(SourceFlag.Default))
+ {
+ count += DefaultMii.TableLength;
+ }
+
+ if (flag.HasFlag(SourceFlag.Database))
+ {
+ count += _miiDatabase.GetCount(metadata);
+ }
+
+ return (uint)count;
+ }
+
+ public ResultCode Move(DatabaseSessionMetadata metadata, int index, CreateId createId)
+ {
+ ResultCode result = _miiDatabase.Move(metadata, index, createId);
+
+ if (result == ResultCode.Success)
+ {
+ result = _miiDatabase.SaveDatabase();
+ }
+
+ return result;
+ }
+
+ public ResultCode Delete(DatabaseSessionMetadata metadata, CreateId createId)
+ {
+ ResultCode result = _miiDatabase.Delete(metadata, createId);
+
+ if (result == ResultCode.Success)
+ {
+ result = _miiDatabase.SaveDatabase();
+ }
+
+ return result;
+ }
+
+ public ResultCode AddOrReplace(DatabaseSessionMetadata metadata, StoreData storeData)
+ {
+ ResultCode result = _miiDatabase.AddOrReplace(metadata, storeData);
+
+ if (result == ResultCode.Success)
+ {
+ result = _miiDatabase.SaveDatabase();
+ }
+
+ return result;
+ }
+
+ public ResultCode ConvertCharInfoToCoreData(CharInfo charInfo, out CoreData coreData)
+ {
+ coreData = new CoreData();
+
+ if (charInfo.IsValid())
+ {
+ return ResultCode.InvalidCharInfo;
+ }
+
+ coreData.SetFromCharInfo(charInfo);
+
+ if (!coreData.Nickname.IsValidForFontRegion(coreData.FontRegion))
+ {
+ coreData.Nickname = Nickname.Question;
+ }
+
+ return ResultCode.Success;
+ }
+
+ public ResultCode GetIndex(DatabaseSessionMetadata metadata, CharInfo charInfo, out int index)
+ {
+ if (!charInfo.IsValid())
+ {
+ index = -1;
+
+ return ResultCode.InvalidCharInfo;
+ }
+
+ if (_miiDatabase.FindIndex(out index, charInfo.CreateId, metadata.MiiKeyCode.IsEnabledSpecialMii()) != ResultCode.Success)
+ {
+ return ResultCode.NotFound;
+ }
+
+ return ResultCode.Success;
+ }
+ }
+}