mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Implement SaveDataFileSystem
This commit is contained in:
parent
2b2b7471ea
commit
2c14770ceb
6 changed files with 181 additions and 54 deletions
|
@ -1068,6 +1068,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
|
|||
2,6395,,,,UnsupportedRollbackOnlyModifiedForApplicationTemporaryFileSystem,
|
||||
2,6396,,,,UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem,
|
||||
2,6397,,,,UnsupportedOperateRangeForRegionSwitchStorage,
|
||||
2,6398,,,,UnsupportedOperateRangeForSaveDataFile,
|
||||
|
||||
2,6400,6449,,,PermissionDenied,
|
||||
2,6403,,,,HostFileSystemOperationDisabled,Returned when opening a host FS on a retail device.
|
||||
|
|
|
|
@ -1960,6 +1960,8 @@ public static class ResultFs
|
|||
public static Result.Base UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem => new Result.Base(ModuleFs, 6396);
|
||||
/// <summary>Error code: 2002-6397; Inner value: 0x31fa02</summary>
|
||||
public static Result.Base UnsupportedOperateRangeForRegionSwitchStorage => new Result.Base(ModuleFs, 6397);
|
||||
/// <summary>Error code: 2002-6398; Inner value: 0x31fc02</summary>
|
||||
public static Result.Base UnsupportedOperateRangeForSaveDataFile => new Result.Base(ModuleFs, 6398);
|
||||
|
||||
/// <summary>Error code: 2002-6400; Range: 6400-6449; Inner value: 0x320002</summary>
|
||||
public static Result.Base PermissionDenied { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 6400, 6449); }
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace LibHac.FsSystem;
|
|||
/// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s to different
|
||||
/// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public abstract class IResultConvertFile : IFile
|
||||
{
|
||||
private UniqueRef<IFile> _baseFile;
|
||||
|
@ -66,7 +66,7 @@ public abstract class IResultConvertFile : IFile
|
|||
/// Wraps an <see cref="IDirectory"/>, converting its returned <see cref="Result"/>s to different
|
||||
/// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public abstract class IResultConvertDirectory : IDirectory
|
||||
{
|
||||
private UniqueRef<IDirectory> _baseDirectory;
|
||||
|
@ -101,7 +101,7 @@ public abstract class IResultConvertDirectory : IDirectory
|
|||
/// Wraps an <see cref="IFileSystem"/>, converting its returned <see cref="Result"/>s to different
|
||||
/// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public abstract class IResultConvertFileSystem<T> : ISaveDataFileSystem where T : IFileSystem
|
||||
{
|
||||
private SharedRef<T> _baseFileSystem;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// ReSharper disable UnusedMember.Local UnusedType.Local
|
||||
#pragma warning disable CS0169 // Field is never used
|
||||
using System;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.FsSystem.Save;
|
||||
|
@ -9,52 +9,92 @@ using LibHac.Os;
|
|||
|
||||
namespace LibHac.FsSystem;
|
||||
|
||||
/// <summary>
|
||||
/// Wraps an <see cref="IFile"/> opened by a <see cref="SaveDataFileSystem"/>
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
file class SaveDataFile : IFile
|
||||
{
|
||||
private UniqueRef<IFile> _file;
|
||||
|
||||
public SaveDataFile(ref UniqueRef<IFile> file)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_file = new UniqueRef<IFile>(ref file);
|
||||
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
|
||||
_file.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
protected override Result DoRead(out long bytesRead, long offset, Span<byte> destination, in ReadOption option)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
|
||||
Result res = _file.Get.Read(out bytesRead, offset, destination);
|
||||
|
||||
if (res.IsFailure())
|
||||
{
|
||||
if (ResultFs.InvalidSaveDataFileReadOffset.Includes(res))
|
||||
{
|
||||
return ResultFs.OutOfRange.LogConverted(res);
|
||||
}
|
||||
|
||||
return res.Miss();
|
||||
}
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source, in WriteOption option)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
|
||||
return _file.Get.Write(offset, source, in option).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoFlush()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
|
||||
return _file.Get.Flush().Ret();
|
||||
}
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
|
||||
return _file.Get.SetSize(size).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoGetSize(out long size)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
|
||||
return _file.Get.GetSize(out size).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
|
||||
ReadOnlySpan<byte> inBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Assert.SdkRequiresNotNull(in _file);
|
||||
|
||||
if (operationId == OperationId.InvalidateCache)
|
||||
return ResultFs.UnsupportedOperateRangeForSaveDataFile.Log();
|
||||
|
||||
return _file.Get.OperateRange(outBuffer, operationId, offset, size, inBuffer).Ret();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads and writes to the file system inside a journal integrity save data image file.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public class SaveDataFileSystem : ISaveDataFileSystem, InternalStorageFileSystemHolder
|
||||
{
|
||||
private SharedRef<IStorage> _baseStorage;
|
||||
|
@ -69,39 +109,75 @@ public class SaveDataFileSystem : ISaveDataFileSystem, InternalStorageFileSystem
|
|||
|
||||
public SaveDataFileSystem()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_baseStorage = new SharedRef<IStorage>();
|
||||
_saveFsDriver = new JournalIntegritySaveDataFileSystemDriver();
|
||||
_cacheObserver = null;
|
||||
_mutex = new SdkMutex();
|
||||
_canCommitProvisionally = false;
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_saveFsDriver.FinalizeObject();
|
||||
_cacheObserver?.Unregister(_spaceId, _saveDataId);
|
||||
|
||||
_saveFsDriver.Dispose();
|
||||
_baseStorage.Destroy();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public static Result ExtractParameters(out JournalIntegritySaveDataParameters outParam, IStorage saveStorage,
|
||||
IBufferManager bufferManager, IMacGenerator macGenerator,
|
||||
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out outParam);
|
||||
|
||||
using var fileSystem = new JournalIntegritySaveDataFileSystemDriver();
|
||||
|
||||
Result res = saveStorage.GetSize(out long size);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var saveSubStorage = new ValueSubStorage(saveStorage, 0, size);
|
||||
res = fileSystem.Initialize(in saveSubStorage, bufferManager, macGenerator, hashGeneratorFactorySelector, minimumVersion);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
fileSystem.ExtractParameters(out outParam);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator,
|
||||
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion, bool canCommitProvisionally)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return Initialize(baseStorage, bufferManager, macGenerator, hashGeneratorFactorySelector, timeStampGetter: null,
|
||||
randomGenerator: null, minimumVersion, canCommitProvisionally).Ret();
|
||||
}
|
||||
|
||||
public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator,
|
||||
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, ISaveDataCommitTimeStampGetter timeStampGetter,
|
||||
RandomDataGenerator randomGenerator, uint minimumVersion, bool canCommitProvisionally)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
Result res = baseStorage.GetSize(out long size);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var baseSubStorage = new ValueSubStorage(baseStorage, 0, size);
|
||||
res = _saveFsDriver.Initialize(in baseSubStorage, bufferManager, macGenerator, hashGeneratorFactorySelector, minimumVersion);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
_commitTimeStampGetter = timeStampGetter;
|
||||
_randomGeneratorForCommit = randomGenerator;
|
||||
_canCommitProvisionally = canCommitProvisionally;
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public Result Initialize(ref readonly SharedRef<IStorage> baseStorage, IBufferManager bufferManager,
|
||||
IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion,
|
||||
bool canCommitProvisionally)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_baseStorage.SetByCopy(in baseStorage);
|
||||
|
||||
return Initialize(_baseStorage.Get, bufferManager, macGenerator, hashGeneratorFactorySelector, minimumVersion,
|
||||
canCommitProvisionally).Ret();
|
||||
}
|
||||
|
||||
public Result Initialize(ref readonly SharedRef<IStorage> baseStorage, IBufferManager bufferManager,
|
||||
|
@ -109,136 +185,184 @@ public class SaveDataFileSystem : ISaveDataFileSystem, InternalStorageFileSystem
|
|||
ISaveDataCommitTimeStampGetter timeStampGetter, RandomDataGenerator randomGenerator, uint minimumVersion,
|
||||
bool canCommitProvisionally)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_baseStorage.SetByCopy(in baseStorage);
|
||||
|
||||
return Initialize(_baseStorage.Get, bufferManager, macGenerator, hashGeneratorFactorySelector, timeStampGetter,
|
||||
randomGenerator, minimumVersion, canCommitProvisionally).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoCreateFile(ref readonly Path path, long size, CreateFileOptions option)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.CreateFile(in path, size, option).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoDeleteFile(ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.DeleteFile(in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoCreateDirectory(ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.CreateDirectory(in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoDeleteDirectory(ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.DeleteDirectory(in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoDeleteDirectoryRecursively(ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.DeleteDirectoryRecursively(in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoCleanDirectoryRecursively(ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.CleanDirectoryRecursively(in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoRenameFile(ref readonly Path currentPath, ref readonly Path newPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.RenameFile(in currentPath, in newPath).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoRenameDirectory(ref readonly Path currentPath, ref readonly Path newPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.RenameDirectory(in currentPath, in newPath).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoGetEntryType(out DirectoryEntryType entryType, ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.GetEntryType(out entryType, in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoOpenFile(ref UniqueRef<IFile> outFile, ref readonly Path path, OpenMode mode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using var file = new UniqueRef<IFile>();
|
||||
Result res = _saveFsDriver.OpenFile(ref file.Ref, in path, mode);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
using var wrapperFile = new UniqueRef<SaveDataFile>(new SaveDataFile(ref file.Ref));
|
||||
|
||||
outFile.Set(ref wrapperFile.Ref);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
protected override Result DoOpenDirectory(ref UniqueRef<IDirectory> outDirectory, ref readonly Path path, OpenDirectoryMode mode)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.OpenDirectory(ref outDirectory, in path, mode).Ret();
|
||||
}
|
||||
|
||||
private Result DoCommit(bool updateTimeStamp)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
if (updateTimeStamp && _commitTimeStampGetter is not null)
|
||||
{
|
||||
Assert.SdkNotNull(_randomGeneratorForCommit);
|
||||
|
||||
Result res = ReadExtraData(out SaveDataExtraData extraData);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
|
||||
res = _commitTimeStampGetter.Get(out long timeStamp);
|
||||
if (res.IsSuccess())
|
||||
extraData.TimeStamp = timeStamp;
|
||||
|
||||
long commitId = 0;
|
||||
do
|
||||
{
|
||||
_randomGeneratorForCommit(SpanHelpers.AsByteSpan(ref commitId));
|
||||
} while (commitId == 0 || commitId == extraData.CommitId);
|
||||
|
||||
extraData.CommitId = commitId;
|
||||
|
||||
res = WriteExtraData(in extraData);
|
||||
if (res.IsFailure()) return res.Miss();
|
||||
}
|
||||
|
||||
return _saveFsDriver.Commit().Ret();
|
||||
}
|
||||
|
||||
protected override Result DoCommit()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return DoCommit(updateTimeStamp: true).Ret();
|
||||
}
|
||||
|
||||
public long GetCounterForBundledCommit()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.GetCounterForBundledCommit();
|
||||
}
|
||||
|
||||
protected override Result DoCommitProvisionally(long counter)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
if (!_canCommitProvisionally)
|
||||
return ResultFs.UnsupportedCommitProvisionallyForSaveDataFileSystem.Log();
|
||||
|
||||
return _saveFsDriver.CommitProvisionally(counter).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoRollback()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
return _saveFsDriver.Rollback().Ret();
|
||||
}
|
||||
|
||||
protected override Result DoGetFreeSpaceSize(out long freeSpace, ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.GetFreeSpaceSize(out freeSpace, in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoGetTotalSpaceSize(out long totalSpace, ref readonly Path path)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.GetTotalSpaceSize(out totalSpace, in path).Ret();
|
||||
}
|
||||
|
||||
protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.GetFileSystemAttribute(out outAttribute).Ret();
|
||||
}
|
||||
|
||||
public override Result WriteExtraData(in SaveDataExtraData extraData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver.WriteExtraData(in Unsafe.As<SaveDataExtraData, JournalIntegritySaveDataFileSystem.ExtraData>(ref Unsafe.AsRef(in extraData))).Ret();
|
||||
}
|
||||
|
||||
public override Result CommitExtraData(bool updateTimeStamp)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return DoCommit(updateTimeStamp).Ret();
|
||||
}
|
||||
|
||||
public override Result ReadExtraData(out SaveDataExtraData extraData)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
UnsafeHelpers.SkipParamInit(out extraData);
|
||||
_saveFsDriver.ReadExtraData(out Unsafe.As<SaveDataExtraData, JournalIntegritySaveDataFileSystem.ExtraData>(ref extraData));
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
public override void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer, SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
public override void RegisterExtraDataAccessorObserver(ISaveDataExtraDataAccessorObserver observer,
|
||||
SaveDataSpaceId spaceId, ulong saveDataId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
_cacheObserver = observer;
|
||||
_spaceId = spaceId;
|
||||
_saveDataId = saveDataId;
|
||||
}
|
||||
|
||||
public override bool IsSaveDataFileSystemCacheEnabled()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override Result RollbackOnlyModified()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
|
||||
|
||||
return _saveFsDriver.RollbackOnlyModified().Ret();
|
||||
}
|
||||
|
||||
public IInternalStorageFileSystem GetInternalStorageFileSystem()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
return _saveFsDriver;
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ namespace LibHac.FsSystem;
|
|||
/// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s
|
||||
/// to save-data-specific <see cref="Result"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public class SaveDataResultConvertFile : IResultConvertFile
|
||||
{
|
||||
private bool _isReconstructible;
|
||||
|
@ -29,13 +29,13 @@ public class SaveDataResultConvertFile : IResultConvertFile
|
|||
/// Wraps an <see cref="IDirectory"/>, converting its returned <see cref="Result"/>s
|
||||
/// to save-data-specific <see cref="Result"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public class SaveDataResultConvertDirectory : IResultConvertDirectory
|
||||
{
|
||||
private bool _isReconstructible;
|
||||
|
||||
public SaveDataResultConvertDirectory(ref UniqueRef<IDirectory> baseDirectory, bool isReconstructible) : base(
|
||||
ref baseDirectory)
|
||||
public SaveDataResultConvertDirectory(ref UniqueRef<IDirectory> baseDirectory, bool isReconstructible)
|
||||
: base(ref baseDirectory)
|
||||
{
|
||||
_isReconstructible = isReconstructible;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class SaveDataResultConvertDirectory : IResultConvertDirectory
|
|||
/// Wraps an <see cref="ISaveDataFileSystem"/>, converting its returned <see cref="Result"/>s
|
||||
/// to save-data-specific <see cref="Result"/>s.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public class SaveDataResultConvertFileSystem : IResultConvertFileSystem<ISaveDataFileSystem>
|
||||
{
|
||||
private bool _isReconstructible;
|
||||
|
|
|
@ -112,7 +112,7 @@ public class SwitchStorage : IStorage
|
|||
/// the provided <see cref="Region"/> will be forwarded to one <see cref="IStorage"/>, and requests outside
|
||||
/// will be forwarded to the other.
|
||||
/// </summary>
|
||||
/// <remarks>Based on nnSdk 14.3.0 (FS 14.1.0)</remarks>
|
||||
/// <remarks>Based on nnSdk 17.5.0 (FS 17.0.0)</remarks>
|
||||
public class RegionSwitchStorage : IStorage
|
||||
{
|
||||
public struct Region
|
||||
|
|
Loading…
Reference in a new issue