Implement SaveDataFileSystem

This commit is contained in:
Alex Barney 2024-03-09 17:47:17 -07:00
parent 2b2b7471ea
commit 2c14770ceb
6 changed files with 181 additions and 54 deletions

View file

@ -1068,6 +1068,7 @@ Module,DescriptionStart,DescriptionEnd,Flags,Namespace,Name,Summary
2,6395,,,,UnsupportedRollbackOnlyModifiedForApplicationTemporaryFileSystem, 2,6395,,,,UnsupportedRollbackOnlyModifiedForApplicationTemporaryFileSystem,
2,6396,,,,UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem, 2,6396,,,,UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem,
2,6397,,,,UnsupportedOperateRangeForRegionSwitchStorage, 2,6397,,,,UnsupportedOperateRangeForRegionSwitchStorage,
2,6398,,,,UnsupportedOperateRangeForSaveDataFile,
2,6400,6449,,,PermissionDenied, 2,6400,6449,,,PermissionDenied,
2,6403,,,,HostFileSystemOperationDisabled,Returned when opening a host FS on a retail device. 2,6403,,,,HostFileSystemOperationDisabled,Returned when opening a host FS on a retail device.

1 Module DescriptionStart DescriptionEnd Flags Namespace Name Summary
1068 3 506 505 OutOfAddressSpace OutOfTransferMemory
1069 3 510 506 SessionClosedForReceive OutOfAddressSpace
1070 3 511 510 SessionClosedForReply SessionClosedForReceive
1071 3 511 SessionClosedForReply
1072 3 512 ReceiveListBroken
1073 4 9 InvalidHandle
1074 4 2001 InvalidArgument

View file

@ -1960,6 +1960,8 @@ public static class ResultFs
public static Result.Base UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem => new Result.Base(ModuleFs, 6396); public static Result.Base UnsupportedRollbackOnlyModifiedForDirectorySaveDataFileSystem => new Result.Base(ModuleFs, 6396);
/// <summary>Error code: 2002-6397; Inner value: 0x31fa02</summary> /// <summary>Error code: 2002-6397; Inner value: 0x31fa02</summary>
public static Result.Base UnsupportedOperateRangeForRegionSwitchStorage => new Result.Base(ModuleFs, 6397); 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> /// <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); } public static Result.Base PermissionDenied { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 6400, 6449); }

View file

@ -10,7 +10,7 @@ namespace LibHac.FsSystem;
/// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s to different /// 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. /// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
/// </summary> /// </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 public abstract class IResultConvertFile : IFile
{ {
private UniqueRef<IFile> _baseFile; 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 /// 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. /// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
/// </summary> /// </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 public abstract class IResultConvertDirectory : IDirectory
{ {
private UniqueRef<IDirectory> _baseDirectory; 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 /// 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. /// <see cref="Result"/>s based on the <see cref="ConvertResult"/> function.
/// </summary> /// </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 public abstract class IResultConvertFileSystem<T> : ISaveDataFileSystem where T : IFileSystem
{ {
private SharedRef<T> _baseFileSystem; private SharedRef<T> _baseFileSystem;

View file

@ -1,7 +1,7 @@
// ReSharper disable UnusedMember.Local UnusedType.Local using System;
#pragma warning disable CS0169 // Field is never used using System.Runtime.CompilerServices;
using System;
using LibHac.Common; using LibHac.Common;
using LibHac.Diag;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
using LibHac.FsSystem.Save; using LibHac.FsSystem.Save;
@ -9,52 +9,92 @@ using LibHac.Os;
namespace LibHac.FsSystem; 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 file class SaveDataFile : IFile
{ {
private UniqueRef<IFile> _file; private UniqueRef<IFile> _file;
public SaveDataFile(ref 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() 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) 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) 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() protected override Result DoFlush()
{ {
throw new NotImplementedException(); Assert.SdkRequiresNotNull(in _file);
return _file.Get.Flush().Ret();
} }
protected override Result DoSetSize(long size) 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) 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, protected override Result DoOperateRange(Span<byte> outBuffer, OperationId operationId, long offset, long size,
ReadOnlySpan<byte> inBuffer) 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 public class SaveDataFileSystem : ISaveDataFileSystem, InternalStorageFileSystemHolder
{ {
private SharedRef<IStorage> _baseStorage; private SharedRef<IStorage> _baseStorage;
@ -69,39 +109,75 @@ public class SaveDataFileSystem : ISaveDataFileSystem, InternalStorageFileSystem
public SaveDataFileSystem() public SaveDataFileSystem()
{ {
throw new NotImplementedException(); _baseStorage = new SharedRef<IStorage>();
_saveFsDriver = new JournalIntegritySaveDataFileSystemDriver();
_cacheObserver = null;
_mutex = new SdkMutex();
_canCommitProvisionally = false;
} }
public override void Dispose() 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, public static Result ExtractParameters(out JournalIntegritySaveDataParameters outParam, IStorage saveStorage,
IBufferManager bufferManager, IMacGenerator macGenerator, IBufferManager bufferManager, IMacGenerator macGenerator,
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion) 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, public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator,
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion, bool canCommitProvisionally) 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, public Result Initialize(IStorage baseStorage, IBufferManager bufferManager, IMacGenerator macGenerator,
IHash256GeneratorFactorySelector hashGeneratorFactorySelector, ISaveDataCommitTimeStampGetter timeStampGetter, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, ISaveDataCommitTimeStampGetter timeStampGetter,
RandomDataGenerator randomGenerator, uint minimumVersion, bool canCommitProvisionally) 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, public Result Initialize(ref readonly SharedRef<IStorage> baseStorage, IBufferManager bufferManager,
IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion, IMacGenerator macGenerator, IHash256GeneratorFactorySelector hashGeneratorFactorySelector, uint minimumVersion,
bool canCommitProvisionally) 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, 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, ISaveDataCommitTimeStampGetter timeStampGetter, RandomDataGenerator randomGenerator, uint minimumVersion,
bool canCommitProvisionally) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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) 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() protected override Result DoCommit()
{ {
throw new NotImplementedException(); return DoCommit(updateTimeStamp: true).Ret();
} }
public long GetCounterForBundledCommit() public long GetCounterForBundledCommit()
{ {
throw new NotImplementedException(); return _saveFsDriver.GetCounterForBundledCommit();
} }
protected override Result DoCommitProvisionally(long counter) 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() 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) 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) 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) protected override Result DoGetFileSystemAttribute(out FileSystemAttribute outAttribute)
{ {
throw new NotImplementedException(); return _saveFsDriver.GetFileSystemAttribute(out outAttribute).Ret();
} }
public override Result WriteExtraData(in SaveDataExtraData extraData) 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) public override Result CommitExtraData(bool updateTimeStamp)
{ {
throw new NotImplementedException(); return DoCommit(updateTimeStamp).Ret();
} }
public override Result ReadExtraData(out SaveDataExtraData extraData) 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() public override bool IsSaveDataFileSystemCacheEnabled()
{ {
throw new NotImplementedException(); return true;
} }
public override Result RollbackOnlyModified() public override Result RollbackOnlyModified()
{ {
throw new NotImplementedException(); using ScopedLock<SdkMutex> scopedLock = ScopedLock.Lock(ref _mutex);
return _saveFsDriver.RollbackOnlyModified().Ret();
} }
public IInternalStorageFileSystem GetInternalStorageFileSystem() public IInternalStorageFileSystem GetInternalStorageFileSystem()
{ {
throw new NotImplementedException(); return _saveFsDriver;
} }
} }

View file

@ -9,7 +9,7 @@ namespace LibHac.FsSystem;
/// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s /// Wraps an <see cref="IFile"/>, converting its returned <see cref="Result"/>s
/// to save-data-specific <see cref="Result"/>s. /// to save-data-specific <see cref="Result"/>s.
/// </summary> /// </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 public class SaveDataResultConvertFile : IResultConvertFile
{ {
private bool _isReconstructible; private bool _isReconstructible;
@ -29,13 +29,13 @@ public class SaveDataResultConvertFile : IResultConvertFile
/// Wraps an <see cref="IDirectory"/>, converting its returned <see cref="Result"/>s /// Wraps an <see cref="IDirectory"/>, converting its returned <see cref="Result"/>s
/// to save-data-specific <see cref="Result"/>s. /// to save-data-specific <see cref="Result"/>s.
/// </summary> /// </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 public class SaveDataResultConvertDirectory : IResultConvertDirectory
{ {
private bool _isReconstructible; private bool _isReconstructible;
public SaveDataResultConvertDirectory(ref UniqueRef<IDirectory> baseDirectory, bool isReconstructible) : base( public SaveDataResultConvertDirectory(ref UniqueRef<IDirectory> baseDirectory, bool isReconstructible)
ref baseDirectory) : base(ref baseDirectory)
{ {
_isReconstructible = isReconstructible; _isReconstructible = isReconstructible;
} }
@ -50,7 +50,7 @@ public class SaveDataResultConvertDirectory : IResultConvertDirectory
/// Wraps an <see cref="ISaveDataFileSystem"/>, converting its returned <see cref="Result"/>s /// Wraps an <see cref="ISaveDataFileSystem"/>, converting its returned <see cref="Result"/>s
/// to save-data-specific <see cref="Result"/>s. /// to save-data-specific <see cref="Result"/>s.
/// </summary> /// </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> public class SaveDataResultConvertFileSystem : IResultConvertFileSystem<ISaveDataFileSystem>
{ {
private bool _isReconstructible; private bool _isReconstructible;

View file

@ -112,7 +112,7 @@ public class SwitchStorage : IStorage
/// the provided <see cref="Region"/> will be forwarded to one <see cref="IStorage"/>, and requests outside /// the provided <see cref="Region"/> will be forwarded to one <see cref="IStorage"/>, and requests outside
/// will be forwarded to the other. /// will be forwarded to the other.
/// </summary> /// </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 class RegionSwitchStorage : IStorage
{ {
public struct Region public struct Region