Update UserFile functions for 13.1.0

This commit is contained in:
Alex Barney 2021-12-24 13:29:35 -07:00
parent 221e2fa608
commit 52d502a793
5 changed files with 174 additions and 3 deletions

View file

@ -0,0 +1,31 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace LibHac.Common.FixedArrays;
[StructLayout(LayoutKind.Sequential)]
public struct Array20<T>
{
public const int Length = 20;
private Array16<T> _0;
private Array4<T> _16;
public ref T this[int i] => ref Items[i];
public Span<T> Items
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.Items), Length);
}
public readonly ReadOnlySpan<T> ItemsRo
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.ItemsRo), Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlySpan<T>(in Array20<T> value) => value.ItemsRo;
}

View file

@ -0,0 +1,32 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace LibHac.Common.FixedArrays;
[StructLayout(LayoutKind.Sequential)]
public struct Array60<T>
{
public const int Length = 60;
private Array32<T> _0;
private Array16<T> _32;
private Array12<T> _48;
public ref T this[int i] => ref Items[i];
public Span<T> Items
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.Items), Length);
}
public readonly ReadOnlySpan<T> ItemsRo
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.ItemsRo), Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlySpan<T>(in Array60<T> value) => value.ItemsRo;
}

View file

@ -7,6 +7,10 @@ using static LibHac.Fs.Impl.AccessLogStrings;
namespace LibHac.Fs.Fsa;
/// <summary>
/// Contains functions for interacting with opened files.
/// </summary>
/// <remarks>Based on FS 13.1.0 (nnSdk 13.4.0)</remarks>
[SkipLocalsInit]
public static class UserFile
{
@ -215,12 +219,75 @@ public static class UserFile
return rc;
}
public static Result InvalidateCache(this FileSystemClient fs, FileHandle handle, long offset, long size)
public static Result InvalidateCache(this FileSystemClient fs, FileHandle handle)
{
Result rc = Get(handle).OperateRange(Span<byte>.Empty, OperationId.InvalidateCache, offset, size,
Result rc = Get(handle).OperateRange(Span<byte>.Empty, OperationId.InvalidateCache, 0, long.MaxValue,
ReadOnlySpan<byte>.Empty);
fs.Impl.AbortIfNeeded(rc);
return rc;
}
}
public static Result QueryUnpreparedRange(this FileSystemClient fs, out Range unpreparedRange, FileHandle handle)
{
UnsafeHelpers.SkipParamInit(out unpreparedRange);
Unsafe.SkipInit(out UnpreparedRangeInfo info);
Result rc = Get(handle).OperateRange(SpanHelpers.AsByteSpan(ref info), OperationId.QueryUnpreparedRange, 0, 0,
ReadOnlySpan<byte>.Empty);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
unpreparedRange = info.Range;
return Result.Success;
}
public static Result QueryUnpreparedRangeDetail(this FileSystemClient fs,
out UnpreparedRangeInfo unpreparedRangeInfo, FileHandle handle)
{
UnsafeHelpers.SkipParamInit(out unpreparedRangeInfo);
Unsafe.SkipInit(out UnpreparedRangeInfo info);
Result rc = Get(handle).OperateRange(SpanHelpers.AsByteSpan(ref info), OperationId.QueryUnpreparedRange, 0, 0,
ReadOnlySpan<byte>.Empty);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
unpreparedRangeInfo = info;
return Result.Success;
}
public static Result QueryLazyLoadCompletionRate(this FileSystemClient fs, out int completionRate,
FileHandle handle, int guideIndex)
{
UnsafeHelpers.SkipParamInit(out completionRate);
Unsafe.SkipInit(out UnpreparedRangeInfo info);
var args = new LazyLoadArguments { GuideIndex = guideIndex };
Result rc = Get(handle).OperateRange(SpanHelpers.AsByteSpan(ref info), OperationId.QueryLazyLoadCompletionRate,
0, 0, SpanHelpers.AsReadOnlyByteSpan(in args));
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
completionRate = info.CompletionRate;
return Result.Success;
}
public static Result ReadyLazyLoadFileForciblyForDebug(this FileSystemClient fs, FileHandle handle, long offset,
long size)
{
Unsafe.SkipInit(out UnpreparedRangeInfo info);
Result rc = Get(handle).OperateRange(SpanHelpers.AsByteSpan(ref info), OperationId.ReadyLazyLoadFile,
offset, size, ReadOnlySpan<byte>.Empty);
fs.Impl.AbortIfNeeded(rc);
if (rc.IsFailure()) return rc.Miss();
return Result.Success;
}
}

View file

@ -0,0 +1,19 @@
using LibHac.Common.FixedArrays;
namespace LibHac.Fs;
public struct UnpreparedRangeInfo
{
public Range Range;
public long FileSize;
public long PreparedRangeSize;
public long TotalReadSize;
public int CompletionRate;
public Array20<byte> Reserved;
}
public struct LazyLoadArguments
{
public int GuideIndex;
public Array60<byte> Reserved;
}

View file

@ -0,0 +1,22 @@
// ReSharper disable InconsistentNaming
using System.Runtime.CompilerServices;
using LibHac.Fs;
using Xunit;
namespace LibHac.Tests.Fs;
public class LazyLoadTypeTests
{
[Fact]
public static void UnpreparedRangeInfoSizeIs0x40()
{
Assert.Equal(0x40, Unsafe.SizeOf<UnpreparedRangeInfo>());
}
[Fact]
public static void LazyLoadArgumentsSizeIs0x40()
{
Assert.Equal(0x40, Unsafe.SizeOf<LazyLoadArguments>());
}
}