Update layout of Arp, Bcat, and some Fs structs

Stop using LayoutKind.Explicit and the Size parameter of StructLayout
This commit is contained in:
Alex Barney 2021-12-29 15:47:20 -07:00
parent 5380902376
commit 57750b896d
22 changed files with 525 additions and 158 deletions

View File

@ -1,12 +1,16 @@
using System.Runtime.InteropServices; namespace LibHac.Arp;
namespace LibHac.Arp;
[StructLayout(LayoutKind.Explicit, Size = 0x10)]
public struct ApplicationLaunchProperty public struct ApplicationLaunchProperty
{ {
[FieldOffset(0x0)] public ApplicationId ApplicationId; public ApplicationId ApplicationId;
[FieldOffset(0x8)] public uint Version; public uint Version;
[FieldOffset(0xC)] public Ncm.StorageId BaseStorageId; public Ncm.StorageId StorageId;
[FieldOffset(0xD)] public Ncm.StorageId UpdateStorageId; public Ncm.StorageId PatchStorageId;
public ApplicationKind ApplicationKind;
} }
public enum ApplicationKind : byte
{
Application = 0,
MicroApplication = 1
}

View File

@ -1,18 +1,15 @@
using System.Runtime.InteropServices; namespace LibHac.Bcat;
namespace LibHac.Bcat;
[StructLayout(LayoutKind.Explicit, Size = 0x38)]
public struct DeliveryCacheDirectoryEntry public struct DeliveryCacheDirectoryEntry
{ {
[FieldOffset(0x00)] public FileName Name; public FileName Name;
[FieldOffset(0x20)] public long Size; public long Size;
[FieldOffset(0x28)] public Digest Digest; public Digest Digest;
public DeliveryCacheDirectoryEntry(ref FileName name, long size, ref Digest digest) public DeliveryCacheDirectoryEntry(in FileName name, long size, in Digest digest)
{ {
Name = name; Name = name;
Size = size; Size = size;
Digest = digest; Digest = digest;
} }
} }

View File

@ -1,28 +1,16 @@
using System; using System.Diagnostics;
using System.Diagnostics; using LibHac.Common.FixedArrays;
using System.Runtime.InteropServices;
using LibHac.Common;
using LibHac.Util; using LibHac.Util;
namespace LibHac.Bcat; namespace LibHac.Bcat;
[DebuggerDisplay("{ToString()}")] [DebuggerDisplay("{ToString()}")]
[StructLayout(LayoutKind.Sequential, Size = 16)]
public struct Digest public struct Digest
{ {
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0; public Array16<byte> Value;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1;
public byte this[int i] public readonly override string ToString()
{ {
get => Bytes[i]; return Value.ItemsRo.ToHexString();
set => Bytes[i] = value;
} }
}
public Span<byte> Bytes => SpanHelpers.AsByteSpan(ref this);
public override string ToString()
{
return Bytes.ToHexString();
}
}

View File

@ -1,33 +1,20 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using LibHac.Common.FixedArrays;
using LibHac.Common;
using LibHac.Util; using LibHac.Util;
namespace LibHac.Bcat; namespace LibHac.Bcat;
[DebuggerDisplay("{ToString()}")] [DebuggerDisplay("{ToString()}")]
[StructLayout(LayoutKind.Sequential, Size = MaxSize)]
public struct DirectoryName public struct DirectoryName
{ {
private const int MaxSize = 0x20; private const int MaxSize = 0x20;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0; public Array32<byte> Value;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy2;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy3;
public byte this[int i] public readonly bool IsValid()
{ {
get => Bytes[i]; ReadOnlySpan<byte> name = Value.ItemsRo;
set => Bytes[i] = value;
}
public Span<byte> Bytes => SpanHelpers.AsByteSpan(ref this);
public bool IsValid()
{
Span<byte> name = Bytes;
int i; int i;
for (i = 0; i < name.Length; i++) for (i = 0; i < name.Length; i++)
@ -45,8 +32,8 @@ public struct DirectoryName
return name[i] == 0; return name[i] == 0;
} }
public override string ToString() public readonly override string ToString()
{ {
return StringUtils.Utf8ZToString(Bytes); return StringUtils.Utf8ZToString(Value.ItemsRo);
} }
} }

View File

@ -1,33 +1,20 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices; using LibHac.Common.FixedArrays;
using LibHac.Common;
using LibHac.Util; using LibHac.Util;
namespace LibHac.Bcat; namespace LibHac.Bcat;
[DebuggerDisplay("{ToString()}")] [DebuggerDisplay("{ToString()}")]
[StructLayout(LayoutKind.Sequential, Size = MaxSize)]
public struct FileName public struct FileName
{ {
private const int MaxSize = 0x20; private const int MaxSize = 0x20;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy0; public Array32<byte> Value;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy1;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy2;
[DebuggerBrowsable(DebuggerBrowsableState.Never)] private ulong _dummy3;
public byte this[int i] public readonly bool IsValid()
{ {
get => Bytes[i]; ReadOnlySpan<byte> name = Value.ItemsRo;
set => Bytes[i] = value;
}
public Span<byte> Bytes => SpanHelpers.AsByteSpan(ref this);
public bool IsValid()
{
Span<byte> name = Bytes;
int i; int i;
for (i = 0; i < name.Length; i++) for (i = 0; i < name.Length; i++)
@ -48,8 +35,8 @@ public struct FileName
return name[i - 1] != '.'; return name[i - 1] != '.';
} }
public override string ToString() public readonly override string ToString()
{ {
return StringUtils.Utf8ZToString(Bytes); return StringUtils.Utf8ZToString(Value.ItemsRo);
} }
} }

View File

@ -1,10 +1,10 @@
using System.Runtime.InteropServices; using LibHac.Common.FixedArrays;
namespace LibHac.Bcat.Impl.Service.Core; namespace LibHac.Bcat.Impl.Service.Core;
[StructLayout(LayoutKind.Explicit, Size = 0x40)]
internal struct DeliveryCacheDirectoryMetaEntry internal struct DeliveryCacheDirectoryMetaEntry
{ {
[FieldOffset(0x00)] public DirectoryName Name; public DirectoryName Name;
[FieldOffset(0x20)] public Digest Digest; public Digest Digest;
} public Array16<byte> Reserved;
}

View File

@ -56,7 +56,7 @@ internal class DeliveryCacheFileMetaAccessor
{ {
for (int i = 0; i < Count; i++) for (int i = 0; i < Count; i++)
{ {
if (StringUtils.CompareCaseInsensitive(Entries[i].Name.Bytes, fileName.Bytes) == 0) if (StringUtils.CompareCaseInsensitive(Entries[i].Name.Value, fileName.Value) == 0)
{ {
entry = Entries[i]; entry = Entries[i];
return Result.Success; return Result.Success;
@ -118,4 +118,4 @@ internal class DeliveryCacheFileMetaAccessor
} }
} }
} }
} }

View File

@ -1,12 +1,12 @@
using System.Runtime.InteropServices; using LibHac.Common.FixedArrays;
namespace LibHac.Bcat.Impl.Service.Core; namespace LibHac.Bcat.Impl.Service.Core;
[StructLayout(LayoutKind.Explicit, Size = 0x80)]
internal struct DeliveryCacheFileMetaEntry internal struct DeliveryCacheFileMetaEntry
{ {
[FieldOffset(0x00)] public FileName Name; public FileName Name;
[FieldOffset(0x20)] public long Id; public long Id;
[FieldOffset(0x28)] public long Size; public long Size;
[FieldOffset(0x30)] public Digest Digest; public Digest Digest;
} public Array64<byte> Reserved;
}

View File

@ -222,9 +222,9 @@ internal class DeliveryCacheStorageManager
AppendMountName(ref sb, applicationId); AppendMountName(ref sb, applicationId);
sb.Append(DirectoriesPath) sb.Append(DirectoriesPath)
.Append(DirectorySeparator).Append(directoryName.Bytes) .Append(DirectorySeparator).Append(directoryName.Value)
.Append(DirectorySeparator).Append(FilesDirectoryName) .Append(DirectorySeparator).Append(FilesDirectoryName)
.Append(DirectorySeparator).Append(fileName.Bytes); .Append(DirectorySeparator).Append(fileName.Value);
} }
} }
@ -237,7 +237,7 @@ internal class DeliveryCacheStorageManager
AppendMountName(ref sb, applicationId); AppendMountName(ref sb, applicationId);
sb.Append(DirectoriesPath) sb.Append(DirectoriesPath)
.Append(DirectorySeparator).Append(directoryName.Bytes) .Append(DirectorySeparator).Append(directoryName.Value)
.Append(DirectorySeparator).Append(FilesMetaFileName); .Append(DirectorySeparator).Append(FilesMetaFileName);
} }
} }
@ -262,7 +262,7 @@ internal class DeliveryCacheStorageManager
AppendMountName(ref sb, applicationId); AppendMountName(ref sb, applicationId);
sb.Append(DirectoriesPath) sb.Append(DirectoriesPath)
.Append(DirectorySeparator).Append(directoryName.Bytes); .Append(DirectorySeparator).Append(directoryName.Value);
} }
} }
@ -395,4 +395,4 @@ internal class DeliveryCacheStorageManager
private static ReadOnlySpan<byte> FilesDirectoryName => // files private static ReadOnlySpan<byte> FilesDirectoryName => // files
new[] { (byte)'f', (byte)'i', (byte)'l', (byte)'e', (byte)'s' }; new[] { (byte)'f', (byte)'i', (byte)'l', (byte)'e', (byte)'s' };
} }

View File

@ -75,7 +75,7 @@ internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService
break; break;
} }
entryBuffer[i] = new DeliveryCacheDirectoryEntry(ref entry.Name, entry.Size, ref entry.Digest); entryBuffer[i] = new DeliveryCacheDirectoryEntry(in entry.Name, entry.Size, in entry.Digest);
} }
entriesRead = i; entriesRead = i;
@ -103,4 +103,4 @@ internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService
{ {
Parent.NotifyCloseDirectory(); Parent.NotifyCloseDirectory();
} }
} }

View File

@ -76,7 +76,7 @@ internal class DeliveryCacheStorageService : IDeliveryCacheStorageService
break; break;
} }
StringUtils.Copy(nameBuffer[i].Bytes, entry.Name.Bytes); StringUtils.Copy(nameBuffer[i].Value.Items, entry.Name.Value);
} }
namesRead = i; namesRead = i;
@ -108,4 +108,4 @@ internal class DeliveryCacheStorageService : IDeliveryCacheStorageService
{ {
Server.GetStorageManager().Release(ApplicationId); Server.GetStorageManager().Release(ApplicationId);
} }
} }

View File

@ -0,0 +1,30 @@
#pragma warning disable CS0169, IDE0051 // Remove unused private members
using System;
using System.Runtime.CompilerServices;
namespace LibHac.Common.FixedArrays;
public struct Array11<T>
{
public const int Length = 11;
private T _1;
private T _2;
private T _3;
private T _4;
private T _5;
private T _6;
private T _7;
private T _8;
private T _9;
private T _10;
private T _11;
public ref T this[int i] => ref Items[i];
public Span<T> Items => SpanHelpers.CreateSpan(ref _1, Length);
public readonly ReadOnlySpan<T> ItemsRo => SpanHelpers.CreateReadOnlySpan(in _1, Length);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator ReadOnlySpan<T>(in Array11<T> value) => value.ItemsRo;
}

View File

@ -0,0 +1,31 @@
#pragma warning disable CS0169, IDE0051 // Remove unused private members
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace LibHac.Common.FixedArrays;
public struct Array24<T>
{
public const int Length = 24;
private Array16<T> _0;
private Array8<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 Array24<T> value) => value.ItemsRo;
}

View File

@ -0,0 +1,32 @@
#pragma warning disable CS0169, IDE0051 // Remove unused private members
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace LibHac.Common.FixedArrays;
public struct Array26<T>
{
public const int Length = 26;
private Array16<T> _0;
private Array8<T> _16;
private Array2<T> _24;
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 Array26<T> value) => value.ItemsRo;
}

View File

@ -0,0 +1,31 @@
#pragma warning disable CS0169, IDE0051 // Remove unused private members
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace LibHac.Common.FixedArrays;
public struct Array36<T>
{
public const int Length = 36;
private Array32<T> _0;
private Array4<T> _32;
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 Array36<T> value) => value.ItemsRo;
}

View File

@ -0,0 +1,32 @@
#pragma warning disable CS0169, IDE0051 // Remove unused private members
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace LibHac.Common.FixedArrays;
public struct Array400<T>
{
public const int Length = 400;
private Array256<T> _0;
private Array128<T> _256;
private Array16<T> _384;
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 Array400<T> value) => value.ItemsRo;
}

View File

@ -1,8 +1,7 @@
using System.Runtime.InteropServices; using LibHac.Common.FixedArrays;
namespace LibHac.Fs; namespace LibHac.Fs;
[StructLayout(LayoutKind.Sequential, Size = 0x80)]
public struct MemoryReportInfo public struct MemoryReportInfo
{ {
public long PooledBufferFreeSizePeak; public long PooledBufferFreeSizePeak;
@ -12,8 +11,10 @@ public struct MemoryReportInfo
public long BufferManagerRetriedCount; public long BufferManagerRetriedCount;
public long ExpHeapFreeSizePeak; public long ExpHeapFreeSizePeak;
public long BufferPoolFreeSizePeak; public long BufferPoolFreeSizePeak;
public long PatrolAllocateSuccessCount; public long PatrolReadAllocateBufferSuccessCount;
public long PatrolAllocateFailureCount; public long PatrolReadAllocateBufferFailureCount;
public long BufferManagerTotalAllocatableSizePeak; public long BufferManagerTotalAllocatableSizePeak;
public long BufferPoolAllocateSizeMax; public long BufferPoolAllocateSizeMax;
} public long PooledBufferFailedIdealAllocationCountOnAsyncAccess;
public Array32<byte> Reserved;
}

View File

@ -1,21 +1,21 @@
using System; using System;
using System.Runtime.InteropServices;
using LibHac.Common; using LibHac.Common;
using LibHac.Common.FixedArrays;
using LibHac.FsSrv.Impl; using LibHac.FsSrv.Impl;
using LibHac.Ncm; using LibHac.Ncm;
using LibHac.Util; using LibHac.Util;
namespace LibHac.Fs; namespace LibHac.Fs;
[StructLayout(LayoutKind.Explicit, Size = 0x40)]
public struct SaveDataAttribute : IEquatable<SaveDataAttribute>, IComparable<SaveDataAttribute> public struct SaveDataAttribute : IEquatable<SaveDataAttribute>, IComparable<SaveDataAttribute>
{ {
[FieldOffset(0x00)] public ProgramId ProgramId; public ProgramId ProgramId;
[FieldOffset(0x08)] public UserId UserId; public UserId UserId;
[FieldOffset(0x18)] public ulong StaticSaveDataId; public ulong StaticSaveDataId;
[FieldOffset(0x20)] public SaveDataType Type; public SaveDataType Type;
[FieldOffset(0x21)] public SaveDataRank Rank; public SaveDataRank Rank;
[FieldOffset(0x22)] public ushort Index; public ushort Index;
public Array24<byte> Reserved;
public SaveDataAttribute(ProgramId programId, SaveDataType type, UserId userId, ulong saveDataId) : this( public SaveDataAttribute(ProgramId programId, SaveDataType type, UserId userId, ulong saveDataId) : this(
programId, type, userId, saveDataId, 0, SaveDataRank.Primary) programId, type, userId, saveDataId, 0, SaveDataRank.Primary)
@ -34,6 +34,7 @@ public struct SaveDataAttribute : IEquatable<SaveDataAttribute>, IComparable<Sav
StaticSaveDataId = saveDataId; StaticSaveDataId = saveDataId;
Index = index; Index = index;
Rank = rank; Rank = rank;
Reserved = new Array24<byte>();
} }
public static Result Make(out SaveDataAttribute attribute, ProgramId programId, SaveDataType type, public static Result Make(out SaveDataAttribute attribute, ProgramId programId, SaveDataType type,
@ -109,16 +110,16 @@ public struct SaveDataAttribute : IEquatable<SaveDataAttribute>, IComparable<Sav
} }
} }
[StructLayout(LayoutKind.Explicit, Size = 0x40)]
public struct SaveDataCreationInfo public struct SaveDataCreationInfo
{ {
[FieldOffset(0x00)] public long Size; public long Size;
[FieldOffset(0x08)] public long JournalSize; public long JournalSize;
[FieldOffset(0x10)] public long BlockSize; public long BlockSize;
[FieldOffset(0x18)] public ulong OwnerId; public ulong OwnerId;
[FieldOffset(0x20)] public SaveDataFlags Flags; public SaveDataFlags Flags;
[FieldOffset(0x24)] public SaveDataSpaceId SpaceId; public SaveDataSpaceId SpaceId;
[FieldOffset(0x25)] public bool IsPseudoSaveData; public bool IsPseudoSaveData;
public Array26<byte> Reserved;
public static Result Make(out SaveDataCreationInfo creationInfo, long size, long journalSize, ulong ownerId, public static Result Make(out SaveDataCreationInfo creationInfo, long size, long journalSize, ulong ownerId,
SaveDataFlags flags, SaveDataSpaceId spaceId) SaveDataFlags flags, SaveDataSpaceId spaceId)
@ -142,17 +143,16 @@ public struct SaveDataCreationInfo
} }
} }
[StructLayout(LayoutKind.Explicit, Size = 0x48)]
public struct SaveDataFilter public struct SaveDataFilter
{ {
[FieldOffset(0x00)] public bool FilterByProgramId; public bool FilterByProgramId;
[FieldOffset(0x01)] public bool FilterBySaveDataType; public bool FilterBySaveDataType;
[FieldOffset(0x02)] public bool FilterByUserId; public bool FilterByUserId;
[FieldOffset(0x03)] public bool FilterBySaveDataId; public bool FilterBySaveDataId;
[FieldOffset(0x04)] public bool FilterByIndex; public bool FilterByIndex;
[FieldOffset(0x05)] public SaveDataRank Rank; public SaveDataRank Rank;
[FieldOffset(0x08)] public SaveDataAttribute Attribute; public SaveDataAttribute Attribute;
public void SetProgramId(ProgramId value) public void SetProgramId(ProgramId value)
{ {
@ -245,49 +245,46 @@ public struct SaveDataFilter
} }
} }
[StructLayout(LayoutKind.Explicit, Size = HashLength)]
public struct HashSalt public struct HashSalt
{ {
private const int HashLength = 0x20; private Array32<byte> _value;
[FieldOffset(0x00)] private byte _hashStart; public Span<byte> Hash => _value.Items;
public readonly ReadOnlySpan<byte> HashRo => _value.ItemsRo;
public Span<byte> Hash => SpanHelpers.CreateSpan(ref _hashStart, HashLength);
public ReadOnlySpan<byte> HashRo => SpanHelpers.CreateReadOnlySpan(in _hashStart, HashLength);
} }
[StructLayout(LayoutKind.Explicit, Size = 0x10)]
public struct SaveDataMetaInfo public struct SaveDataMetaInfo
{ {
[FieldOffset(0)] public int Size; public int Size;
[FieldOffset(4)] public SaveDataMetaType Type; public SaveDataMetaType Type;
public Array11<byte> Reserved;
} }
[StructLayout(LayoutKind.Explicit, Size = 0x60)]
public struct SaveDataInfo public struct SaveDataInfo
{ {
[FieldOffset(0x00)] public ulong SaveDataId; public ulong SaveDataId;
[FieldOffset(0x08)] public SaveDataSpaceId SpaceId; public SaveDataSpaceId SpaceId;
[FieldOffset(0x09)] public SaveDataType Type; public SaveDataType Type;
[FieldOffset(0x10)] public UserId UserId; public UserId UserId;
[FieldOffset(0x20)] public ulong StaticSaveDataId; public ulong StaticSaveDataId;
[FieldOffset(0x28)] public ProgramId ProgramId; public ProgramId ProgramId;
[FieldOffset(0x30)] public long Size; public long Size;
[FieldOffset(0x38)] public ushort Index; public ushort Index;
[FieldOffset(0x3A)] public SaveDataRank Rank; public SaveDataRank Rank;
[FieldOffset(0x3B)] public SaveDataState State; public SaveDataState State;
public Array36<byte> Reserved;
} }
[StructLayout(LayoutKind.Explicit, Size = 0x200)]
public struct SaveDataExtraData public struct SaveDataExtraData
{ {
[FieldOffset(0x00)] public SaveDataAttribute Attribute; public SaveDataAttribute Attribute;
[FieldOffset(0x40)] public ulong OwnerId; public ulong OwnerId;
[FieldOffset(0x48)] public long TimeStamp; public long TimeStamp;
[FieldOffset(0x50)] public SaveDataFlags Flags; public SaveDataFlags Flags;
[FieldOffset(0x58)] public long DataSize; public long DataSize;
[FieldOffset(0x60)] public long JournalSize; public long JournalSize;
[FieldOffset(0x68)] public long CommitId; public long CommitId;
public Array400<byte> Reserved;
} }
public struct CommitOption public struct CommitOption

View File

@ -112,8 +112,8 @@ public class StatusReportServiceImpl
if (_config.GetPatrolAllocateCounts != null) if (_config.GetPatrolAllocateCounts != null)
{ {
_config.GetPatrolAllocateCounts(out reportInfo.PatrolAllocateSuccessCount, _config.GetPatrolAllocateCounts(out reportInfo.PatrolReadAllocateBufferSuccessCount,
out reportInfo.PatrolAllocateFailureCount); out reportInfo.PatrolReadAllocateBufferFailureCount);
} }
return Result.Success; return Result.Success;
@ -139,4 +139,4 @@ public class StatusReportServiceImpl
return 0; return 0;
} }
} }
} }

View File

@ -0,0 +1,23 @@
using System.Runtime.CompilerServices;
using LibHac.Arp;
using Xunit;
using static LibHac.Tests.Common.Layout;
namespace LibHac.Tests.Arp;
public class TypeLayoutTests
{
[Fact]
public static void ApplicationLaunchProperty_Layout()
{
var s = new ApplicationLaunchProperty();
Assert.Equal(0x10, Unsafe.SizeOf<ApplicationLaunchProperty>());
Assert.Equal(0x0, GetOffset(in s, in s.ApplicationId));
Assert.Equal(0x8, GetOffset(in s, in s.Version));
Assert.Equal(0xC, GetOffset(in s, in s.StorageId));
Assert.Equal(0xD, GetOffset(in s, in s.PatchStorageId));
Assert.Equal(0xE, GetOffset(in s, in s.ApplicationKind));
}
}

View File

@ -0,0 +1,78 @@
using System.Runtime.CompilerServices;
using LibHac.Bcat;
using LibHac.Bcat.Impl.Service.Core;
using Xunit;
using static LibHac.Tests.Common.Layout;
namespace LibHac.Tests.Bcat;
public class TypeLayoutTests
{
[Fact]
public static void Digest_Layout()
{
var s = new Digest();
Assert.Equal(0x10, Unsafe.SizeOf<Digest>());
Assert.Equal(0x0, GetOffset(in s, in s.Value));
}
[Fact]
public static void DirectoryName_Layout()
{
var s = new DirectoryName();
Assert.Equal(0x20, Unsafe.SizeOf<DirectoryName>());
Assert.Equal(0x0, GetOffset(in s, in s.Value));
}
[Fact]
public static void FileName_Layout()
{
var s = new FileName();
Assert.Equal(0x20, Unsafe.SizeOf<FileName>());
Assert.Equal(0x0, GetOffset(in s, in s.Value));
}
[Fact]
public static void DeliveryCacheDirectoryEntry_Layout()
{
var s = new DeliveryCacheDirectoryEntry();
Assert.Equal(0x38, Unsafe.SizeOf<DeliveryCacheDirectoryEntry>());
Assert.Equal(0x00, GetOffset(in s, in s.Name));
Assert.Equal(0x20, GetOffset(in s, in s.Size));
Assert.Equal(0x28, GetOffset(in s, in s.Digest));
}
[Fact]
public static void DeliveryCacheDirectoryMetaEntry_Layout()
{
var s = new DeliveryCacheDirectoryMetaEntry();
Assert.Equal(0x40, Unsafe.SizeOf<DeliveryCacheDirectoryMetaEntry>());
Assert.Equal(0x00, GetOffset(in s, in s.Name));
Assert.Equal(0x20, GetOffset(in s, in s.Digest));
Assert.Equal(0x30, GetOffset(in s, in s.Reserved));
}
[Fact]
public static void DeliveryCacheFileMetaEntry_Layout()
{
var s = new DeliveryCacheFileMetaEntry();
Assert.Equal(0x80, Unsafe.SizeOf<DeliveryCacheFileMetaEntry>());
Assert.Equal(0x00, GetOffset(in s, in s.Name));
Assert.Equal(0x20, GetOffset(in s, in s.Id));
Assert.Equal(0x28, GetOffset(in s, in s.Size));
Assert.Equal(0x30, GetOffset(in s, in s.Digest));
Assert.Equal(0x40, GetOffset(in s, in s.Reserved));
}
}

View File

@ -0,0 +1,149 @@
using System.Runtime.CompilerServices;
using LibHac.Fs;
using Xunit;
using static LibHac.Tests.Common.Layout;
namespace LibHac.Tests.Fs;
public class TypeLayoutTests
{
[Fact]
public static void SaveDataAttribute_Layout()
{
var s = new SaveDataAttribute();
Assert.Equal(0x40, Unsafe.SizeOf<SaveDataAttribute>());
Assert.Equal(0x00, GetOffset(in s, in s.ProgramId));
Assert.Equal(0x08, GetOffset(in s, in s.UserId));
Assert.Equal(0x18, GetOffset(in s, in s.StaticSaveDataId));
Assert.Equal(0x20, GetOffset(in s, in s.Type));
Assert.Equal(0x21, GetOffset(in s, in s.Rank));
Assert.Equal(0x22, GetOffset(in s, in s.Index));
Assert.Equal(0x24, GetOffset(in s, in s.Reserved));
}
[Fact]
public static void SaveDataCreationInfo_Layout()
{
var s = new SaveDataCreationInfo();
Assert.Equal(0x40, Unsafe.SizeOf<SaveDataCreationInfo>());
Assert.Equal(0x00, GetOffset(in s, in s.Size));
Assert.Equal(0x08, GetOffset(in s, in s.JournalSize));
Assert.Equal(0x10, GetOffset(in s, in s.BlockSize));
Assert.Equal(0x18, GetOffset(in s, in s.OwnerId));
Assert.Equal(0x20, GetOffset(in s, in s.Flags));
Assert.Equal(0x24, GetOffset(in s, in s.SpaceId));
Assert.Equal(0x25, GetOffset(in s, in s.IsPseudoSaveData));
Assert.Equal(0x26, GetOffset(in s, in s.Reserved));
}
[Fact]
public static void SaveDataFilter_Layout()
{
var s = new SaveDataFilter();
Assert.Equal(0x48, Unsafe.SizeOf<SaveDataFilter>());
Assert.Equal(0, GetOffset(in s, in s.FilterByProgramId));
Assert.Equal(1, GetOffset(in s, in s.FilterBySaveDataType));
Assert.Equal(2, GetOffset(in s, in s.FilterByUserId));
Assert.Equal(3, GetOffset(in s, in s.FilterBySaveDataId));
Assert.Equal(4, GetOffset(in s, in s.FilterByIndex));
Assert.Equal(5, GetOffset(in s, in s.Rank));
Assert.Equal(8, GetOffset(in s, in s.Attribute));
}
[Fact]
public static void SaveDataMetaInfo_Layout()
{
var s = new SaveDataMetaInfo();
Assert.Equal(0x10, Unsafe.SizeOf<SaveDataMetaInfo>());
Assert.Equal(0, GetOffset(in s, in s.Size));
Assert.Equal(4, GetOffset(in s, in s.Type));
Assert.Equal(5, GetOffset(in s, in s.Reserved));
}
[Fact]
public static void HashSalt_Layout()
{
var s = new HashSalt();
Assert.Equal(0x20, Unsafe.SizeOf<HashSalt>());
Assert.Equal(0, GetOffset(in s, in s.Hash[0]));
}
[Fact]
public static void SaveDataInfo_Layout()
{
var s = new SaveDataInfo();
Assert.Equal(0x60, Unsafe.SizeOf<SaveDataInfo>());
Assert.Equal(0x00, GetOffset(in s, in s.SaveDataId));
Assert.Equal(0x08, GetOffset(in s, in s.SpaceId));
Assert.Equal(0x09, GetOffset(in s, in s.Type));
Assert.Equal(0x10, GetOffset(in s, in s.UserId));
Assert.Equal(0x20, GetOffset(in s, in s.StaticSaveDataId));
Assert.Equal(0x28, GetOffset(in s, in s.ProgramId));
Assert.Equal(0x30, GetOffset(in s, in s.Size));
Assert.Equal(0x38, GetOffset(in s, in s.Index));
Assert.Equal(0x3A, GetOffset(in s, in s.Rank));
Assert.Equal(0x3B, GetOffset(in s, in s.State));
Assert.Equal(0x3C, GetOffset(in s, in s.Reserved));
}
[Fact]
public static void SaveDataExtraData_Layout()
{
var s = new SaveDataExtraData();
Assert.Equal(0x200, Unsafe.SizeOf<SaveDataExtraData>());
Assert.Equal(0x00, GetOffset(in s, in s.Attribute));
Assert.Equal(0x40, GetOffset(in s, in s.OwnerId));
Assert.Equal(0x48, GetOffset(in s, in s.TimeStamp));
Assert.Equal(0x50, GetOffset(in s, in s.Flags));
Assert.Equal(0x58, GetOffset(in s, in s.DataSize));
Assert.Equal(0x60, GetOffset(in s, in s.JournalSize));
Assert.Equal(0x68, GetOffset(in s, in s.CommitId));
Assert.Equal(0x70, GetOffset(in s, in s.Reserved));
}
[Fact]
public static void CommitOption_Layout()
{
var s = new CommitOption();
Assert.Equal(4, Unsafe.SizeOf<CommitOption>());
Assert.Equal(0, GetOffset(in s, in s.Flags));
}
[Fact]
public static void MemoryReportInfo_Layout()
{
var s = new MemoryReportInfo();
Assert.Equal(0x80, Unsafe.SizeOf<MemoryReportInfo>());
Assert.Equal(0x00, GetOffset(in s, in s.PooledBufferFreeSizePeak));
Assert.Equal(0x08, GetOffset(in s, in s.PooledBufferRetriedCount));
Assert.Equal(0x10, GetOffset(in s, in s.PooledBufferReduceAllocationCount));
Assert.Equal(0x18, GetOffset(in s, in s.BufferManagerFreeSizePeak));
Assert.Equal(0x20, GetOffset(in s, in s.BufferManagerRetriedCount));
Assert.Equal(0x28, GetOffset(in s, in s.ExpHeapFreeSizePeak));
Assert.Equal(0x30, GetOffset(in s, in s.BufferPoolFreeSizePeak));
Assert.Equal(0x38, GetOffset(in s, in s.PatrolReadAllocateBufferSuccessCount));
Assert.Equal(0x40, GetOffset(in s, in s.PatrolReadAllocateBufferFailureCount));
Assert.Equal(0x48, GetOffset(in s, in s.BufferManagerTotalAllocatableSizePeak));
Assert.Equal(0x50, GetOffset(in s, in s.BufferPoolAllocateSizeMax));
Assert.Equal(0x58, GetOffset(in s, in s.PooledBufferFailedIdealAllocationCountOnAsyncAccess));
Assert.Equal(0x60, GetOffset(in s, in s.Reserved));
}
}