From 213515f06f7cacfec6c164c3a93adfd14dc2eaea Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Tue, 12 Sep 2023 21:42:01 -0700 Subject: [PATCH] Diff some more storage related classes with FS 16 --- src/LibHac/Common/FixedArrays/Array436.cs | 36 ++++++++++++ .../Fs/ApplicationSaveDataManagement.cs | 2 +- src/LibHac/Fs/Impl/SdHandleManager.cs | 2 +- src/LibHac/Fs/MemoryStorage.cs | 3 +- .../FsCreator/GameCardFileSystemCreator.cs | 4 +- .../FsSrv/FsCreator/GameCardStorageCreator.cs | 2 +- .../FsSrv/FsCreator/SdStorageCreator.cs | 2 +- .../Storage/IStorageDeviceManagerFactory.cs | 2 +- src/LibHac/FsSrv/Storage/Sf/IStorageDevice.cs | 2 +- .../FsSrv/Storage/Sf/IStorageDeviceManager.cs | 2 +- .../Storage/Sf/IStorageDeviceOperator.cs | 2 +- .../FsSystem/CardDeviceDetectionEvent.cs | 2 +- src/LibHac/FsSystem/PartitionFileSystem.cs | 12 ++-- .../FsSystem/PartitionFileSystemMeta.cs | 6 +- src/LibHac/Gc/GameCardEmulated.cs | 2 +- src/LibHac/Gc/Impl/GameCardImplTypes.cs | 56 ++++++++++++++++++- tests/LibHac.Tests/Gc/TypeLayoutTests.cs | 39 +++++++++++++ 17 files changed, 151 insertions(+), 25 deletions(-) create mode 100644 src/LibHac/Common/FixedArrays/Array436.cs diff --git a/src/LibHac/Common/FixedArrays/Array436.cs b/src/LibHac/Common/FixedArrays/Array436.cs new file mode 100644 index 00000000..a552b403 --- /dev/null +++ b/src/LibHac/Common/FixedArrays/Array436.cs @@ -0,0 +1,36 @@ +#pragma warning disable CS0169, CS0649, IDE0051 // Field is never used, Field is never assigned to, Remove unused private members +using System; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace LibHac.Common.FixedArrays; + +public struct Array436 +{ + public const int Length = 436; + + private Array256 _0; + private Array128 _256; + private Array32 _384; + private Array20 _416; + + [UnscopedRef] public ref T this[int i] => ref Items[i]; + + [UnscopedRef] + public Span Items + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.Items), Length); + } + + [UnscopedRef] + public readonly ReadOnlySpan ItemsRo + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => SpanHelpers.CreateSpan(ref MemoryMarshal.GetReference(_0.ItemsRo), Length); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static implicit operator ReadOnlySpan(in Array436 value) => value.ItemsRo; +} \ No newline at end of file diff --git a/src/LibHac/Fs/ApplicationSaveDataManagement.cs b/src/LibHac/Fs/ApplicationSaveDataManagement.cs index 8a3fe7a4..2b6f8ed6 100644 --- a/src/LibHac/Fs/ApplicationSaveDataManagement.cs +++ b/src/LibHac/Fs/ApplicationSaveDataManagement.cs @@ -12,7 +12,7 @@ namespace LibHac.Fs; /// /// Contains functions for ensuring that an application's save data exists and is the correct size. /// -/// Based on nnSdk 15.3.0 +/// Based on nnSdk 16.2.0 public static class ApplicationSaveDataManagement { private const int LeftoverFreeSpaceRequiredForUserAndDeviceSaves = 0x4000; diff --git a/src/LibHac/Fs/Impl/SdHandleManager.cs b/src/LibHac/Fs/Impl/SdHandleManager.cs index 16e53134..95e32156 100644 --- a/src/LibHac/Fs/Impl/SdHandleManager.cs +++ b/src/LibHac/Fs/Impl/SdHandleManager.cs @@ -6,7 +6,7 @@ namespace LibHac.Fs.Impl; /// /// Allows getting the current handle for the SD card and checking to see if a provided handle is still valid. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) internal class SdHandleManager : IDeviceHandleManager { // LibHac addition diff --git a/src/LibHac/Fs/MemoryStorage.cs b/src/LibHac/Fs/MemoryStorage.cs index ed43bd8c..6e72b0cd 100644 --- a/src/LibHac/Fs/MemoryStorage.cs +++ b/src/LibHac/Fs/MemoryStorage.cs @@ -8,7 +8,7 @@ namespace LibHac.Fs; /// /// Allows interacting with a array via the interface. /// -/// Based on nnSdk 14.3.0 (FS 14.1.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class MemoryStorage : IStorage { private byte[] _buffer; @@ -25,7 +25,6 @@ public class MemoryStorage : IStorage Assert.SdkRequiresNotNull(buffer); Assert.SdkRequiresInRange(size, 0, buffer.Length); - // ReSharper disable once ConditionIsAlwaysTrueOrFalse Abort.DoAbortUnless(buffer is null || 0 <= size && size < buffer.Length); _buffer = buffer; diff --git a/src/LibHac/FsSrv/FsCreator/GameCardFileSystemCreator.cs b/src/LibHac/FsSrv/FsCreator/GameCardFileSystemCreator.cs index cc7b363e..fe67525a 100644 --- a/src/LibHac/FsSrv/FsCreator/GameCardFileSystemCreator.cs +++ b/src/LibHac/FsSrv/FsCreator/GameCardFileSystemCreator.cs @@ -16,7 +16,7 @@ namespace LibHac.FsSrv.FsCreator; /// /// Reads the root partition of a game card and handles opening the various partitions it contains. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class GameCardRootPartition : IDisposable { private const int LogoPartitionSizeMax = 0x12000; @@ -209,7 +209,7 @@ public class GameCardRootPartition : IDisposable /// /// Creates s of the various partitions contained by the currently mounted game card. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class GameCardFileSystemCreator : IGameCardFileSystemCreator { private MemoryResource _allocator; diff --git a/src/LibHac/FsSrv/FsCreator/GameCardStorageCreator.cs b/src/LibHac/FsSrv/FsCreator/GameCardStorageCreator.cs index c40bed32..3fc68a72 100644 --- a/src/LibHac/FsSrv/FsCreator/GameCardStorageCreator.cs +++ b/src/LibHac/FsSrv/FsCreator/GameCardStorageCreator.cs @@ -8,7 +8,7 @@ namespace LibHac.FsSrv.FsCreator; /// /// Creates s to the currently mounted game card. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class GameCardStorageCreator : IGameCardStorageCreator { // LibHac addition so we can access fssrv::storage functions diff --git a/src/LibHac/FsSrv/FsCreator/SdStorageCreator.cs b/src/LibHac/FsSrv/FsCreator/SdStorageCreator.cs index c4193ce4..bbb101ee 100644 --- a/src/LibHac/FsSrv/FsCreator/SdStorageCreator.cs +++ b/src/LibHac/FsSrv/FsCreator/SdStorageCreator.cs @@ -7,7 +7,7 @@ namespace LibHac.FsSrv.FsCreator; /// /// Creates s for accessing the inserted SD card's storage. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class SdStorageCreator : ISdStorageCreator { // LibHac addition diff --git a/src/LibHac/FsSrv/Storage/IStorageDeviceManagerFactory.cs b/src/LibHac/FsSrv/Storage/IStorageDeviceManagerFactory.cs index 1aa55838..87626133 100644 --- a/src/LibHac/FsSrv/Storage/IStorageDeviceManagerFactory.cs +++ b/src/LibHac/FsSrv/Storage/IStorageDeviceManagerFactory.cs @@ -9,7 +9,7 @@ namespace LibHac.FsSrv.Storage; /// Manages setting storage devices as ready or not ready, and allows opening s for /// each storage device. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public interface IStorageDeviceManagerFactory : IDisposable { Result Create(ref SharedRef outDeviceManager, StorageDevicePortId portId); diff --git a/src/LibHac/FsSrv/Storage/Sf/IStorageDevice.cs b/src/LibHac/FsSrv/Storage/Sf/IStorageDevice.cs index 3304d159..1ee271a7 100644 --- a/src/LibHac/FsSrv/Storage/Sf/IStorageDevice.cs +++ b/src/LibHac/FsSrv/Storage/Sf/IStorageDevice.cs @@ -9,7 +9,7 @@ namespace LibHac.FsSrv.Storage.Sf; /// Allows reading from or writing to a storage device's storage like an , getting or validating /// its current handle, and opening an for the storage device. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public interface IStorageDevice : IStorage { Result GetHandle(out uint handle); diff --git a/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceManager.cs b/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceManager.cs index 2da4c897..7a724de8 100644 --- a/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceManager.cs +++ b/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceManager.cs @@ -8,7 +8,7 @@ namespace LibHac.FsSrv.Storage.Sf; /// /// Allows getting the current state of a storage device and opening various interfaces to operate on it. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public interface IStorageDeviceManager : IDisposable { Result IsInserted(out bool isInserted); diff --git a/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceOperator.cs b/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceOperator.cs index 0c21954e..e8453f52 100644 --- a/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceOperator.cs +++ b/src/LibHac/FsSrv/Storage/Sf/IStorageDeviceOperator.cs @@ -9,7 +9,7 @@ namespace LibHac.FsSrv.Storage.Sf; /// /// Operation IDs are not common between implementers of the interface. Every implementer will have its own operations /// and expected input data. -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public interface IStorageDeviceOperator : IDisposable { Result Operate(int operationId); diff --git a/src/LibHac/FsSystem/CardDeviceDetectionEvent.cs b/src/LibHac/FsSystem/CardDeviceDetectionEvent.cs index edf2dd61..3d210443 100644 --- a/src/LibHac/FsSystem/CardDeviceDetectionEvent.cs +++ b/src/LibHac/FsSystem/CardDeviceDetectionEvent.cs @@ -12,7 +12,7 @@ namespace LibHac.FsSystem; /// /// Base class for classes that manage registering events and signaling them when a card device is inserted or removed. /// -/// Based on nnSdk 14.3.0 (FS 14.1.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) internal class CardDeviceDetectionEventManager : IDisposable { private LinkedList _events; diff --git a/src/LibHac/FsSystem/PartitionFileSystem.cs b/src/LibHac/FsSystem/PartitionFileSystem.cs index f42de22a..d5575363 100644 --- a/src/LibHac/FsSystem/PartitionFileSystem.cs +++ b/src/LibHac/FsSystem/PartitionFileSystem.cs @@ -16,7 +16,7 @@ namespace LibHac.FsSystem; /// /// The original allocator in FS simply calls nn::fs::detail::Allocate and /// nn::fs::detail::Deallocate. In our implementation we use the shared .NET . -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) file sealed class DefaultAllocatorForPartitionFileSystem : MemoryResource { public static readonly DefaultAllocatorForPartitionFileSystem Instance = new(); @@ -50,7 +50,7 @@ file sealed class DefaultAllocatorForPartitionFileSystem : MemoryResource /// Reads a standard partition file system. These files start with "PFS0" and are typically found inside NCAs /// or as .nsp files. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class PartitionFileSystem : PartitionFileSystemCore /// Reads a hashed partition file system. These files start with "HFS0" and are typically found inside XCIs. /// -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class Sha256PartitionFileSystem : PartitionFileSystemCoreA traits class that provides values used to read and build the metadata. /// The type of the header at the beginning of the metadata. /// The type of the entries in the file table in the metadata. -/// Based on nnSdk 15.3.0 (FS 15.0.0) +/// Based on nnSdk 16.2.0 (FS 16.0.0) public class PartitionFileSystemCore : IFileSystem where TMetaData : PartitionFileSystemMetaCore, new() where TFormat : IPartitionFileSystemFormat @@ -93,7 +93,7 @@ public class PartitionFileSystemCore : IFil /// /// Provides access to a file from a . /// - /// Based on nnSdk 15.3.0 (FS 15.0.0) + /// Based on nnSdk 16.2.0 (FS 16.0.0) private class PartitionFile : IFile { private TEntry _partitionEntry; @@ -337,7 +337,7 @@ public class PartitionFileSystemCore : IFil /// /// A cannot contain any /// subdirectories, so a will only access the root directory. - /// Based on nnSdk 15.3.0 (FS 15.0.0) + /// Based on nnSdk 16.2.0 (FS 16.0.0) private class PartitionDirectory : IDirectory { private int _currentIndex; diff --git a/src/LibHac/FsSystem/PartitionFileSystemMeta.cs b/src/LibHac/FsSystem/PartitionFileSystemMeta.cs index 4cb1f40e..038f59e0 100644 --- a/src/LibHac/FsSystem/PartitionFileSystemMeta.cs +++ b/src/LibHac/FsSystem/PartitionFileSystemMeta.cs @@ -59,7 +59,7 @@ namespace LibHac.FsSystem /// A traits class that provides values used to read and build the metadata. /// The type of the header at the beginning of the metadata. /// The type of the entries in the file table in the metadata. - /// Based on nnSdk 15.3.0 (FS 15.0.0) + /// Based on nnSdk 16.2.0 (FS 16.0.0) public class PartitionFileSystemMetaCore : IDisposable where TFormat : IPartitionFileSystemFormat where THeader : unmanaged, IPartitionFileSystemHeader @@ -290,7 +290,7 @@ namespace LibHac.FsSystem /// /// Reads the metadata for a . /// - /// Based on nnSdk 15.3.0 (FS 15.0.0) + /// Based on nnSdk 16.2.0 (FS 16.0.0) public class Sha256PartitionFileSystemMeta : PartitionFileSystemMetaCore { public Result Initialize(IStorage baseStorage, MemoryResource allocator, ReadOnlySpan hash) @@ -360,7 +360,7 @@ namespace LibHac.FsSystem /// /// Reads the metadata for a . /// - /// Based on nnSdk 15.3.0 (FS 15.0.0) + /// Based on nnSdk 16.2.0 (FS 16.0.0) public class PartitionFileSystemMeta : PartitionFileSystemMetaCore { } } \ No newline at end of file diff --git a/src/LibHac/Gc/GameCardEmulated.cs b/src/LibHac/Gc/GameCardEmulated.cs index 27c82038..c9572c7a 100644 --- a/src/LibHac/Gc/GameCardEmulated.cs +++ b/src/LibHac/Gc/GameCardEmulated.cs @@ -277,7 +277,7 @@ public sealed class GameCardEmulated : IGcApi int limArea = (int)_cardHeader.LimAreaPage; bool isNormal = pageAddress < limArea; - bool isSecure = (pageAddress + pageCount - 1) >= limArea; + bool isSecure = pageAddress + pageCount - 1 >= limArea; // Reads cannot span the boundary between the normal area and secure area. if (isNormal && isSecure) diff --git a/src/LibHac/Gc/Impl/GameCardImplTypes.cs b/src/LibHac/Gc/Impl/GameCardImplTypes.cs index b9863201..175c64cc 100644 --- a/src/LibHac/Gc/Impl/GameCardImplTypes.cs +++ b/src/LibHac/Gc/Impl/GameCardImplTypes.cs @@ -1,4 +1,5 @@ -using LibHac.Common.FixedArrays; +using System.Runtime.InteropServices; +using LibHac.Common.FixedArrays; namespace LibHac.Gc.Impl; @@ -22,9 +23,60 @@ public struct CardId3 public Array4 Reserved; } +public enum DevCardRomSize : byte +{ + // ReSharper disable InconsistentNaming + Size1GB = 3, + Size2GB = 4, + Size4GB = 5, + Size8GB = 6, + Size16GB = 7, + Size32GB = 8 + // ReSharper restore InconsistentNaming +} + +public enum DevCardNandSize : byte +{ + // ReSharper disable InconsistentNaming + Size16GB = 7, + Size32GB = 8, + Size64GB = 9 + // ReSharper restore InconsistentNaming +} + +[StructLayout(LayoutKind.Sequential)] public struct DevCardParameter { - public Array512 Data; + public CardId1 CardId1; + public CardId2 CardId2; + public CardId3 CardId3; + public uint RomAreaStartAddr; + public uint BackupAreaStartAddr; + public Array3 ReservedAreaStartAddr; + public DevCardRomSize RomSize; + public Array2 WaitCycle1ForRead; + public Array2 WaitCycle2ForRead; + public byte SpeedChangeEmulateWaitCycle1FrequencyForRead; + public Array3 SpeedChangeEmulateWaitCycle1ForRead; + public byte SpeedChangeEmulateWaitCycle2FrequencyForRead; + public Array3 SpeedChangeEmulateWaitCycle2ForRead; + public Array3 FirstReadPageWaitCycleForRead; + public Array2 WaitCycle1ForWrite; + public Array3 WaitCycle2ForWrite; + public byte SpeedChangeEmulateWaitCycle1FrequencyForWrite; + public Array3 SpeedChangeEmulateWaitCycle1ForWrite; + public byte SpeedChangeEmulateWaitCycle2FrequencyForWrite; + public Array3 SpeedChangeEmulateWaitCycle2ForWrite; + public Array2 WaitCycle1ForSetAccessPattern; + public Array3 WaitCycle2ForSetAccessPattern; + public Array3 WaitCycleForRefresh; + public Array3 WaitCycleForSetKey; + public Array3 WaitCycleForIRdInit; + public Array3 WaitCycleForISetInit1; + public Array3 WaitCycleForISetGen; + public Array3 WaitCycleForISetInit2; + public DevCardNandSize NandSize; + public Array436 Reserved; } public struct CardInitialDataPayload diff --git a/tests/LibHac.Tests/Gc/TypeLayoutTests.cs b/tests/LibHac.Tests/Gc/TypeLayoutTests.cs index 4d78ab5d..85a59a7a 100644 --- a/tests/LibHac.Tests/Gc/TypeLayoutTests.cs +++ b/tests/LibHac.Tests/Gc/TypeLayoutTests.cs @@ -101,6 +101,45 @@ public class TypeLayoutTests Assert.Equal(0x30, GetOffset(in s, in s.AuthNonce)); } + [Fact] + public static void DevCardParameter_Layout() + { + var s = new DevCardParameter(); + + Assert.Equal(0x200, Unsafe.SizeOf()); + + Assert.Equal(0x00, GetOffset(in s, in s.CardId1)); + Assert.Equal(0x04, GetOffset(in s, in s.CardId2)); + Assert.Equal(0x08, GetOffset(in s, in s.CardId3)); + Assert.Equal(0x0C, GetOffset(in s, in s.RomAreaStartAddr)); + Assert.Equal(0x10, GetOffset(in s, in s.BackupAreaStartAddr)); + Assert.Equal(0x14, GetOffset(in s, in s.ReservedAreaStartAddr)); + Assert.Equal(0x17, GetOffset(in s, in s.RomSize)); + Assert.Equal(0x18, GetOffset(in s, in s.WaitCycle1ForRead)); + Assert.Equal(0x1A, GetOffset(in s, in s.WaitCycle2ForRead)); + Assert.Equal(0x1C, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle1FrequencyForRead)); + Assert.Equal(0x1D, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle1ForRead)); + Assert.Equal(0x20, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle2FrequencyForRead)); + Assert.Equal(0x21, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle2ForRead)); + Assert.Equal(0x24, GetOffset(in s, in s.FirstReadPageWaitCycleForRead)); + Assert.Equal(0x27, GetOffset(in s, in s.WaitCycle1ForWrite)); + Assert.Equal(0x29, GetOffset(in s, in s.WaitCycle2ForWrite)); + Assert.Equal(0x2C, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle1FrequencyForWrite)); + Assert.Equal(0x2D, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle1ForWrite)); + Assert.Equal(0x30, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle2FrequencyForWrite)); + Assert.Equal(0x31, GetOffset(in s, in s.SpeedChangeEmulateWaitCycle2ForWrite)); + Assert.Equal(0x34, GetOffset(in s, in s.WaitCycle1ForSetAccessPattern)); + Assert.Equal(0x36, GetOffset(in s, in s.WaitCycle2ForSetAccessPattern)); + Assert.Equal(0x39, GetOffset(in s, in s.WaitCycleForRefresh)); + Assert.Equal(0x3C, GetOffset(in s, in s.WaitCycleForSetKey)); + Assert.Equal(0x3F, GetOffset(in s, in s.WaitCycleForIRdInit)); + Assert.Equal(0x42, GetOffset(in s, in s.WaitCycleForISetInit1)); + Assert.Equal(0x45, GetOffset(in s, in s.WaitCycleForISetGen)); + Assert.Equal(0x48, GetOffset(in s, in s.WaitCycleForISetInit2)); + Assert.Equal(0x4B, GetOffset(in s, in s.NandSize)); + Assert.Equal(0x4C, GetOffset(in s, in s.Reserved)); + } + [Fact] public static void CardInitialData_Layout() {