mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2026-05-16 18:25:47 +00:00
[HLE] Fix StoreData layout and implement IDatabaseService.Append (#43)
- Fixes `StoreData` layout/update handling so `UpdateLatest` returns the stored Mii data correctly. - Implements `IDatabaseService.Append` (https://switchbrew.org/wiki/Shared_Database_services#IDatabaseService) Also adds regression tests for `UpdateLatest` and `Append`. (Might) fix Mario Kart 8 Deluxe crashing on first boot due to failed Mii verification check (due to custom Mii from emulator), and potentially Tomodachi Life: Living the Dream for the "Import Mii from system" option. Co-authored-by: yell0wsuit <5692900+yell0wsuit@users.noreply.github.com> Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/43
This commit is contained in:
@@ -81,8 +81,10 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode UpdateLatest<T>(DatabaseSessionMetadata metadata, IStoredData<T> oldMiiData, SourceFlag flag, IStoredData<T> newMiiData) where T : unmanaged
|
||||
public ResultCode UpdateLatest<T>(DatabaseSessionMetadata metadata, T oldMiiData, SourceFlag flag, out T newMiiData) where T : unmanaged, IStoredData<T>
|
||||
{
|
||||
newMiiData = default;
|
||||
|
||||
if (!flag.HasFlag(SourceFlag.Database))
|
||||
{
|
||||
return ResultCode.NotFound;
|
||||
@@ -106,7 +108,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||
|
||||
newMiiData.SetFromStoreData(storeData);
|
||||
|
||||
if (oldMiiData == newMiiData)
|
||||
if (oldMiiData.Equals(newMiiData))
|
||||
{
|
||||
return ResultCode.NotUpdated;
|
||||
}
|
||||
@@ -286,6 +288,18 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResultCode Append(DatabaseSessionMetadata metadata, CharInfo charInfo)
|
||||
{
|
||||
ResultCode result = _miiDatabase.Append(metadata, _utilityImpl, charInfo);
|
||||
|
||||
if (result == ResultCode.Success)
|
||||
{
|
||||
result = _miiDatabase.SaveDatabase();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public ResultCode ConvertCharInfoToCoreData(CharInfo charInfo, out CoreData coreData)
|
||||
{
|
||||
coreData = new CoreData();
|
||||
|
||||
@@ -449,6 +449,32 @@ namespace Ryujinx.HLE.HOS.Services.Mii
|
||||
return ResultCode.Success;
|
||||
}
|
||||
|
||||
public ResultCode Append(DatabaseSessionMetadata metadata, UtilityImpl utilityImpl, CharInfo charInfo)
|
||||
{
|
||||
if (!charInfo.IsValid())
|
||||
{
|
||||
return ResultCode.InvalidCharInfo;
|
||||
}
|
||||
|
||||
if (charInfo.Type == 1)
|
||||
{
|
||||
return ResultCode.InvalidOperationOnSpecialMii;
|
||||
}
|
||||
|
||||
CoreData coreData = new();
|
||||
coreData.SetFromCharInfo(charInfo);
|
||||
|
||||
StoreData storeData;
|
||||
|
||||
do
|
||||
{
|
||||
storeData = StoreData.BuildFromCoreData(utilityImpl, coreData);
|
||||
}
|
||||
while (_database.GetIndexByCreatorId(out _, storeData.CreateId));
|
||||
|
||||
return AddOrReplace(metadata, storeData);
|
||||
}
|
||||
|
||||
public ResultCode Delete(DatabaseSessionMetadata metadata, CreateId createId)
|
||||
{
|
||||
if (!_database.GetIndexByCreatorId(out int index, createId))
|
||||
|
||||
@@ -54,9 +54,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.StaticService
|
||||
|
||||
protected override ResultCode UpdateLatest(CharInfo oldCharInfo, SourceFlag flag, out CharInfo newCharInfo)
|
||||
{
|
||||
newCharInfo = default;
|
||||
|
||||
return _database.UpdateLatest(_metadata, oldCharInfo, flag, newCharInfo);
|
||||
return _database.UpdateLatest(_metadata, oldCharInfo, flag, out newCharInfo);
|
||||
}
|
||||
|
||||
protected override ResultCode BuildRandom(Age age, Gender gender, Race race, out CharInfo charInfo)
|
||||
@@ -113,14 +111,14 @@ namespace Ryujinx.HLE.HOS.Services.Mii.StaticService
|
||||
|
||||
protected override ResultCode UpdateLatest1(StoreData oldStoreData, SourceFlag flag, out StoreData newStoreData)
|
||||
{
|
||||
newStoreData = default;
|
||||
|
||||
if (!_isSystem)
|
||||
{
|
||||
newStoreData = default;
|
||||
|
||||
return ResultCode.PermissionDenied;
|
||||
}
|
||||
|
||||
return _database.UpdateLatest(_metadata, oldStoreData, flag, newStoreData);
|
||||
return _database.UpdateLatest(_metadata, oldStoreData, flag, out newStoreData);
|
||||
}
|
||||
|
||||
protected override ResultCode FindIndex(CreateId createId, bool isSpecial, out int index)
|
||||
@@ -262,5 +260,10 @@ namespace Ryujinx.HLE.HOS.Services.Mii.StaticService
|
||||
{
|
||||
return _database.ConvertCharInfoToCoreData(charInfo, out coreData);
|
||||
}
|
||||
|
||||
protected override ResultCode Append(CharInfo charInfo)
|
||||
{
|
||||
return _database.Append(_metadata, charInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -340,6 +340,15 @@ namespace Ryujinx.HLE.HOS.Services.Mii.StaticService
|
||||
return result;
|
||||
}
|
||||
|
||||
[CommandCmif(26)] // 10.2.0+
|
||||
// Append(nn::mii::CharInfo char_info)
|
||||
public ResultCode Append(ServiceCtx context)
|
||||
{
|
||||
CharInfo charInfo = context.RequestData.ReadStruct<CharInfo>();
|
||||
|
||||
return Append(charInfo);
|
||||
}
|
||||
|
||||
private Span<byte> CreateByteSpanFromBuffer(ServiceCtx context, IpcBuffDesc ipcBuff, bool isOutput)
|
||||
{
|
||||
byte[] rawData;
|
||||
@@ -421,5 +430,7 @@ namespace Ryujinx.HLE.HOS.Services.Mii.StaticService
|
||||
protected abstract ResultCode ConvertCoreDataToCharInfo(CoreData coreData, out CharInfo charInfo);
|
||||
|
||||
protected abstract ResultCode ConvertCharInfoToCoreData(CharInfo charInfo, out CoreData coreData);
|
||||
|
||||
protected abstract ResultCode Append(CharInfo charInfo);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user