mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add SaveDataIndexerLite
This commit is contained in:
parent
6abe565de1
commit
9c402df18a
3 changed files with 238 additions and 5 deletions
|
@ -285,7 +285,7 @@ namespace LibHac.FsService
|
|||
|
||||
SaveDataAttribute indexerKey = attribute;
|
||||
|
||||
if (attribute.SaveDataId != 0 || attribute.UserId == UserId.Zero)
|
||||
if (attribute.SaveDataId != 0 && attribute.UserId == UserId.Zero)
|
||||
{
|
||||
saveDataId = attribute.SaveDataId;
|
||||
|
||||
|
@ -486,7 +486,8 @@ namespace LibHac.FsService
|
|||
using SaveDataIndexerReader reader = tmpReader;
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
reader.Indexer.Get(out SaveDataIndexerValue indexerValue, ref indexerKey);
|
||||
rc = reader.Indexer.Get(out SaveDataIndexerValue indexerValue, ref indexerKey);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
SaveDataSpaceId indexerSpaceId = GetSpaceIdForIndexer(spaceId);
|
||||
|
||||
|
|
224
src/LibHac/FsService/SaveDataIndexerLite.cs
Normal file
224
src/LibHac/FsService/SaveDataIndexerLite.cs
Normal file
|
@ -0,0 +1,224 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService
|
||||
{
|
||||
public class SaveDataIndexerLite : ISaveDataIndexer
|
||||
{
|
||||
private object Locker { get; } = new object();
|
||||
private ulong CurrentSaveDataId { get; set; } = 0x4000000000000000;
|
||||
private bool IsKeyValueSet { get; set; }
|
||||
|
||||
private SaveDataAttribute _key;
|
||||
private SaveDataIndexerValue _value;
|
||||
|
||||
public Result Commit()
|
||||
{
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Add(out ulong saveDataId, ref SaveDataAttribute key)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _key.Equals(key))
|
||||
{
|
||||
saveDataId = default;
|
||||
return ResultFs.SaveDataPathAlreadyExists.Log();
|
||||
}
|
||||
|
||||
_key = key;
|
||||
IsKeyValueSet = true;
|
||||
|
||||
_value = new SaveDataIndexerValue { SaveDataId = CurrentSaveDataId };
|
||||
saveDataId = CurrentSaveDataId;
|
||||
CurrentSaveDataId++;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public Result Get(out SaveDataIndexerValue value, ref SaveDataAttribute key)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _key.Equals(key))
|
||||
{
|
||||
value = _value;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result AddSystemSaveData(ref SaveDataAttribute key)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _key.Equals(key))
|
||||
{
|
||||
return ResultFs.SaveDataPathAlreadyExists.Log();
|
||||
}
|
||||
|
||||
_key = key;
|
||||
IsKeyValueSet = true;
|
||||
|
||||
_value = new SaveDataIndexerValue();
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsFull()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public Result Delete(ulong saveDataId)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _value.SaveDataId == saveDataId)
|
||||
{
|
||||
IsKeyValueSet = false;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result SetSpaceId(ulong saveDataId, SaveDataSpaceId spaceId)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _value.SaveDataId == saveDataId)
|
||||
{
|
||||
_value.SpaceId = spaceId;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result SetSize(ulong saveDataId, long size)
|
||||
{
|
||||
// Nintendo doesn't lock in this function for some reason
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _value.SaveDataId == saveDataId)
|
||||
{
|
||||
_value.Size = size;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result SetState(ulong saveDataId, SaveDataState state)
|
||||
{
|
||||
// Nintendo doesn't lock in this function for some reason
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _value.SaveDataId == saveDataId)
|
||||
{
|
||||
_value.State = state;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result GetKey(out SaveDataAttribute key, ulong saveDataId)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _value.SaveDataId == saveDataId)
|
||||
{
|
||||
key = _key;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
key = default;
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public Result GetBySaveDataId(out SaveDataIndexerValue value, ulong saveDataId)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (IsKeyValueSet && _value.SaveDataId == saveDataId)
|
||||
{
|
||||
value = _value;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return ResultFs.TargetNotFound.Log();
|
||||
}
|
||||
}
|
||||
|
||||
public int GetCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public Result OpenSaveDataInfoReader(out ISaveDataInfoReader infoReader)
|
||||
{
|
||||
if (IsKeyValueSet)
|
||||
{
|
||||
infoReader = new SaveDataIndexerLiteInfoReader(ref _key, ref _value);
|
||||
}
|
||||
else
|
||||
{
|
||||
infoReader = new SaveDataIndexerLiteInfoReader();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
private class SaveDataIndexerLiteInfoReader : ISaveDataInfoReader
|
||||
{
|
||||
private bool _finishedIterating;
|
||||
private SaveDataInfo _info;
|
||||
|
||||
public SaveDataIndexerLiteInfoReader()
|
||||
{
|
||||
_finishedIterating = true;
|
||||
}
|
||||
|
||||
public SaveDataIndexerLiteInfoReader(ref SaveDataAttribute key, ref SaveDataIndexerValue value)
|
||||
{
|
||||
SaveDataIndexer.GetSaveDataInfo(out _info, ref key, ref value);
|
||||
}
|
||||
|
||||
public Result ReadSaveDataInfo(out long readCount, Span<byte> saveDataInfoBuffer)
|
||||
{
|
||||
Span<SaveDataInfo> outInfo = MemoryMarshal.Cast<byte, SaveDataInfo>(saveDataInfoBuffer);
|
||||
|
||||
// Nintendo doesn't check if the buffer is too small here
|
||||
if (_finishedIterating || outInfo.IsEmpty)
|
||||
{
|
||||
readCount = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
outInfo[0] = _info;
|
||||
readCount = 1;
|
||||
_finishedIterating = true;
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public void Dispose() { }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.FsService
|
||||
|
@ -11,6 +10,7 @@ namespace LibHac.FsService
|
|||
|
||||
private IndexerHolder _bisIndexer = new IndexerHolder(new object());
|
||||
private IndexerHolder _sdCardIndexer = new IndexerHolder(new object());
|
||||
private IndexerHolder _tempIndexer = new IndexerHolder(new object());
|
||||
private IndexerHolder _safeIndexer = new IndexerHolder(new object());
|
||||
private IndexerHolder _properSystemIndexer = new IndexerHolder(new object());
|
||||
|
||||
|
@ -51,7 +51,15 @@ namespace LibHac.FsService
|
|||
return Result.Success;
|
||||
|
||||
case SaveDataSpaceId.Temporary:
|
||||
throw new NotImplementedException();
|
||||
Monitor.Enter(_tempIndexer.Locker);
|
||||
|
||||
if (!_tempIndexer.IsInitialized)
|
||||
{
|
||||
_tempIndexer.Indexer = new SaveDataIndexerLite();
|
||||
}
|
||||
|
||||
reader = new SaveDataIndexerReader(_tempIndexer.Indexer, _tempIndexer.Locker);
|
||||
return Result.Success;
|
||||
|
||||
case SaveDataSpaceId.ProperSystem:
|
||||
Monitor.Enter(_safeIndexer.Locker);
|
||||
|
|
Loading…
Reference in a new issue