mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2025-02-09 13:14:46 +01:00
Move some functions from Utilities to LibHac.Util.*
This commit is contained in:
parent
7fcb0054e4
commit
acce155341
@ -340,7 +340,7 @@ namespace LibHac.Boot
|
||||
int pk11Size = Unsafe.SizeOf<Package1Pk11Header>() + GetSectionSize(Package1Section.WarmBoot) +
|
||||
GetSectionSize(Package1Section.Bootloader) + GetSectionSize(Package1Section.SecureMonitor);
|
||||
|
||||
pk11Size = Utilities.AlignUp(pk11Size, 0x10);
|
||||
pk11Size = Alignment.AlignUp(pk11Size, 0x10);
|
||||
|
||||
return pk11Size == Pk11Size;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using LibHac.Common;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.Crypto.Detail
|
||||
{
|
||||
@ -25,7 +26,7 @@ namespace LibHac.Crypto.Detail
|
||||
|
||||
public void Transform(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
int blockCount = Utilities.DivideByRoundUp(input.Length, Aes.BlockSize);
|
||||
int blockCount = BitUtil.DivideUp(input.Length, Aes.BlockSize);
|
||||
int length = blockCount * Aes.BlockSize;
|
||||
|
||||
using var counterBuffer = new RentedArray<byte>(length);
|
||||
|
@ -59,7 +59,7 @@ namespace LibHac.Crypto
|
||||
|
||||
BigInteger dp = d % (p - BigInteger.One);
|
||||
BigInteger dq = d % (q - BigInteger.One);
|
||||
BigInteger inverseQ = Utilities.ModInverse(q, p);
|
||||
BigInteger inverseQ = ModInverse(q, p);
|
||||
|
||||
byte[] nBytes = n.ToByteArray();
|
||||
int modLen = nBytes.Length;
|
||||
@ -138,7 +138,7 @@ namespace LibHac.Crypto
|
||||
do
|
||||
{
|
||||
rng.NextBytes(rndBuf);
|
||||
g = Utilities.GetBigInteger(rndBuf);
|
||||
g = GetBigInteger(rndBuf);
|
||||
}
|
||||
while (g >= n);
|
||||
|
||||
@ -179,5 +179,66 @@ namespace LibHac.Crypto
|
||||
|
||||
return (p, q);
|
||||
}
|
||||
|
||||
private static BigInteger GetBigInteger(this ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
var signPadded = new byte[bytes.Length + 1];
|
||||
bytes.CopyTo(signPadded.AsSpan(1));
|
||||
Array.Reverse(signPadded);
|
||||
return new BigInteger(signPadded);
|
||||
}
|
||||
|
||||
private static byte[] GetBytes(this BigInteger value, int size)
|
||||
{
|
||||
byte[] bytes = value.ToByteArray();
|
||||
|
||||
if (size == -1)
|
||||
{
|
||||
size = bytes.Length;
|
||||
}
|
||||
|
||||
if (bytes.Length > size + 1)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
|
||||
}
|
||||
|
||||
if (bytes.Length == size + 1 && bytes[bytes.Length - 1] != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
|
||||
}
|
||||
|
||||
Array.Resize(ref bytes, size);
|
||||
Array.Reverse(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private static BigInteger ModInverse(BigInteger e, BigInteger n)
|
||||
{
|
||||
BigInteger r = n;
|
||||
BigInteger newR = e;
|
||||
BigInteger t = 0;
|
||||
BigInteger newT = 1;
|
||||
|
||||
while (newR != 0)
|
||||
{
|
||||
BigInteger quotient = r / newR;
|
||||
BigInteger temp;
|
||||
|
||||
temp = t;
|
||||
t = newT;
|
||||
newT = temp - quotient * newT;
|
||||
|
||||
temp = r;
|
||||
r = newR;
|
||||
newR = temp - quotient * newR;
|
||||
}
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
t = t + n;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ using LibHac.Account;
|
||||
using LibHac.Fs.Shim;
|
||||
using LibHac.Ncm;
|
||||
using LibHac.Ns;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.Fs
|
||||
{
|
||||
@ -101,7 +102,7 @@ namespace LibHac.Fs
|
||||
|
||||
if (queryRc.IsFailure()) return queryRc;
|
||||
|
||||
requiredSizeSum += Utilities.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000;
|
||||
requiredSizeSum += Alignment.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -118,7 +119,7 @@ namespace LibHac.Fs
|
||||
|
||||
if (queryRc.IsFailure()) return queryRc;
|
||||
|
||||
requiredSizeSum += Utilities.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000;
|
||||
requiredSizeSum += Alignment.AlignUp(tempSaveTotalSize, 0x4000) + 0x4000;
|
||||
}
|
||||
else if (ResultFs.PathAlreadyExists.Includes(createRc))
|
||||
{
|
||||
@ -162,7 +163,7 @@ namespace LibHac.Fs
|
||||
Result queryRc = fs.QuerySaveDataTotalSize(out long totalSize, dataSize, journalSize);
|
||||
if (queryRc.IsFailure()) return queryRc;
|
||||
|
||||
requiredSize += Utilities.AlignUp(totalSize, 0x4000) + baseSize;
|
||||
requiredSize += Alignment.AlignUp(totalSize, 0x4000) + baseSize;
|
||||
}
|
||||
else if (!ResultFs.PathAlreadyExists.Includes(rc))
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSrv.Impl
|
||||
{
|
||||
@ -127,7 +128,7 @@ namespace LibHac.FsSrv.Impl
|
||||
accessControlData.Slice(data.SaveDataOwnerInfoOffset + sizeof(int), infoCount);
|
||||
|
||||
// The ID list must be 4-byte aligned
|
||||
int idsOffset = Utilities.AlignUp(data.SaveDataOwnerInfoOffset + sizeof(int) + infoCount, 4);
|
||||
int idsOffset = Alignment.AlignUp(data.SaveDataOwnerInfoOffset + sizeof(int) + infoCount, 4);
|
||||
ReadOnlySpan<ulong> ids = MemoryMarshal.Cast<byte, ulong>(
|
||||
accessControlData.Slice(idsOffset, infoCount * sizeof(ulong)));
|
||||
|
||||
|
@ -3,6 +3,7 @@ using System.Buffers;
|
||||
using System.Buffers.Binary;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -36,7 +37,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
public int TransformBlock(Span<byte> data)
|
||||
{
|
||||
int blockCount = Utilities.DivideByRoundUp(data.Length, BlockSizeBytes);
|
||||
int blockCount = BitUtil.DivideUp(data.Length, BlockSizeBytes);
|
||||
int length = blockCount * BlockSizeBytes;
|
||||
|
||||
byte[] counterXor = ArrayPool<byte>.Shared.Rent(length);
|
||||
|
@ -28,6 +28,7 @@ using System;
|
||||
using System.Buffers;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -83,7 +84,7 @@ namespace LibHac.FsSystem
|
||||
/* get number of blocks */
|
||||
int m = count >> 4;
|
||||
int mo = count & 15;
|
||||
int alignedCount = Utilities.AlignUp(count, BlockSizeBytes);
|
||||
int alignedCount = Alignment.AlignUp(count, BlockSizeBytes);
|
||||
|
||||
/* for i = 0 to m-2 do */
|
||||
if (mo == 0)
|
||||
|
@ -2,6 +2,7 @@
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -37,7 +38,7 @@ namespace LibHac.FsSystem
|
||||
ThrowHelper.ThrowResult(ResultFs.AesXtsFileHeaderInvalidKeys.Value, "NAX0 key derivation failed.");
|
||||
}
|
||||
|
||||
if (HeaderLength + Utilities.AlignUp(Header.Size, 0x10) > fileSize)
|
||||
if (HeaderLength + Alignment.AlignUp(Header.Size, 0x10) > fileSize)
|
||||
{
|
||||
ThrowHelper.ThrowResult(ResultFs.AesXtsFileTooShort.Value, "NAX0 key derivation failed.");
|
||||
}
|
||||
@ -118,7 +119,7 @@ namespace LibHac.FsSystem
|
||||
Result rc = BaseFile.Write(0, Header.ToBytes(false));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
return BaseStorage.SetSize(Utilities.AlignUp(size, 0x10));
|
||||
return BaseStorage.SetSize(Alignment.AlignUp(size, 0x10));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
|
@ -3,6 +3,7 @@ using System.Diagnostics;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -62,7 +63,7 @@ namespace LibHac.FsSystem
|
||||
/// <param name="key">The 256-bit key containing a 128-bit data key followed by a 128-bit tweak key.</param>
|
||||
public Result CreateFile(U8Span path, long size, CreateFileOptions options, byte[] key)
|
||||
{
|
||||
long containerSize = AesXtsFile.HeaderLength + Utilities.AlignUp(size, 0x10);
|
||||
long containerSize = AesXtsFile.HeaderLength + Alignment.AlignUp(size, 0x10);
|
||||
|
||||
Result rc = BaseFileSystem.CreateFile(path, containerSize, options);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
@ -6,6 +6,7 @@ using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -37,7 +38,7 @@ namespace LibHac.FsSystem
|
||||
Assert.AssertTrue(entrySize >= sizeof(long));
|
||||
Assert.AssertTrue(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.AssertTrue(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.AssertTrue(Utilities.IsPowerOfTwo(nodeSize));
|
||||
Assert.AssertTrue(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.AssertTrue(!IsInitialized());
|
||||
|
||||
// Ensure valid entry count.
|
||||
@ -139,7 +140,7 @@ namespace LibHac.FsSystem
|
||||
Assert.AssertTrue(entrySize >= sizeof(long));
|
||||
Assert.AssertTrue(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.AssertTrue(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.AssertTrue(Utilities.IsPowerOfTwo(nodeSize));
|
||||
Assert.AssertTrue(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.AssertTrue(entryCount >= 0);
|
||||
|
||||
if (entryCount <= 0)
|
||||
@ -153,7 +154,7 @@ namespace LibHac.FsSystem
|
||||
Assert.AssertTrue(entrySize >= sizeof(long));
|
||||
Assert.AssertTrue(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.AssertTrue(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.AssertTrue(Utilities.IsPowerOfTwo(nodeSize));
|
||||
Assert.AssertTrue(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
Assert.AssertTrue(entryCount >= 0);
|
||||
|
||||
if (entryCount <= 0)
|
||||
@ -175,7 +176,7 @@ namespace LibHac.FsSystem
|
||||
private static int GetEntrySetCount(long nodeSize, long entrySize, int entryCount)
|
||||
{
|
||||
int entryCountPerNode = GetEntryCount(nodeSize, entrySize);
|
||||
return Utilities.DivideByRoundUp(entryCount, entryCountPerNode);
|
||||
return BitUtil.DivideUp(entryCount, entryCountPerNode);
|
||||
}
|
||||
|
||||
public static int GetNodeL2Count(long nodeSize, long entrySize, int entryCount)
|
||||
@ -186,10 +187,10 @@ namespace LibHac.FsSystem
|
||||
if (entrySetCount <= offsetCountPerNode)
|
||||
return 0;
|
||||
|
||||
int nodeL2Count = Utilities.DivideByRoundUp(entrySetCount, offsetCountPerNode);
|
||||
int nodeL2Count = BitUtil.DivideUp(entrySetCount, offsetCountPerNode);
|
||||
Abort.DoAbortUnless(nodeL2Count <= offsetCountPerNode);
|
||||
|
||||
return Utilities.DivideByRoundUp(entrySetCount - (offsetCountPerNode - (nodeL2Count - 1)), offsetCountPerNode);
|
||||
return BitUtil.DivideUp(entrySetCount - (offsetCountPerNode - (nodeL2Count - 1)), offsetCountPerNode);
|
||||
}
|
||||
|
||||
private static long GetBucketTreeEntryOffset(long entrySetOffset, long entrySize, int entryIndex)
|
||||
|
@ -4,6 +4,7 @@ using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Diag;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -44,7 +45,7 @@ namespace LibHac.FsSystem
|
||||
Assert.AssertTrue(entrySize >= sizeof(long));
|
||||
Assert.AssertTrue(nodeSize >= entrySize + Unsafe.SizeOf<NodeHeader>());
|
||||
Assert.AssertTrue(NodeSizeMin <= nodeSize && nodeSize <= NodeSizeMax);
|
||||
Assert.AssertTrue(Utilities.IsPowerOfTwo(nodeSize));
|
||||
Assert.AssertTrue(BitUtil.IsPowerOfTwo(nodeSize));
|
||||
|
||||
if (headerStorage is null || nodeStorage is null || entryStorage is null)
|
||||
return ResultFs.NullptrArgument.Log();
|
||||
@ -267,7 +268,7 @@ namespace LibHac.FsSystem
|
||||
if (rc.IsFailure()) return rc;
|
||||
}
|
||||
|
||||
int l2NodeIndex = Utilities.DivideByRoundUp(CurrentL2OffsetIndex, OffsetsPerNode) - 2;
|
||||
int l2NodeIndex = BitUtil.DivideUp(CurrentL2OffsetIndex, OffsetsPerNode) - 2;
|
||||
int indexInL2Node = CurrentL2OffsetIndex % OffsetsPerNode;
|
||||
|
||||
// Finalize the current L2 node if needed
|
||||
@ -291,7 +292,7 @@ namespace LibHac.FsSystem
|
||||
// L1 count depends on the existence or absence of L2 nodes
|
||||
if (CurrentL2OffsetIndex == 0)
|
||||
{
|
||||
l1NodeHeader.Count = Utilities.DivideByRoundUp(CurrentEntryIndex, EntriesPerEntrySet);
|
||||
l1NodeHeader.Count = BitUtil.DivideUp(CurrentEntryIndex, EntriesPerEntrySet);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -6,6 +6,7 @@ using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -227,7 +228,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
if (size == 0) return 1;
|
||||
|
||||
return (int)Utilities.DivideByRoundUp(size, subFileSize);
|
||||
return (int)BitUtil.DivideUp(size, subFileSize);
|
||||
}
|
||||
|
||||
private static long QuerySubFileSize(int subFileIndex, long totalSize, long subFileSize)
|
||||
|
@ -4,6 +4,7 @@ using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -37,7 +38,7 @@ namespace LibHac.FsSystem
|
||||
var levelData = new IntegrityVerificationStorage(levelInfo[i], Levels[i - 1], integrityCheckLevel, leaveOpen);
|
||||
levelData.GetSize(out long levelSize).ThrowIfFailure();
|
||||
|
||||
int cacheCount = Math.Min((int)Utilities.DivideByRoundUp(levelSize, levelInfo[i].BlockSize), 4);
|
||||
int cacheCount = Math.Min((int)BitUtil.DivideUp(levelSize, levelInfo[i].BlockSize), 4);
|
||||
|
||||
Levels[i] = new CachedStorage(levelData, cacheCount, leaveOpen);
|
||||
LevelValidities[i - 1] = levelData.BlockValidities;
|
||||
@ -145,7 +146,7 @@ namespace LibHac.FsSystem
|
||||
IntegrityVerificationStorage storage = IntegrityStorages[IntegrityStorages.Length - 1];
|
||||
|
||||
long blockSize = storage.SectorSize;
|
||||
int blockCount = (int)Utilities.DivideByRoundUp(Length, blockSize);
|
||||
int blockCount = (int)BitUtil.DivideUp(Length, blockSize);
|
||||
|
||||
var buffer = new byte[blockSize];
|
||||
var result = Validity.Valid;
|
||||
|
@ -150,7 +150,7 @@ namespace LibHac.FsSystem.NcaUtils
|
||||
|
||||
BaseStorage.GetSize(out long baseSize).ThrowIfFailure();
|
||||
|
||||
if (!Utilities.IsSubRange(offset, size, baseSize))
|
||||
if (!IsSubRange(offset, size, baseSize))
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Section offset (0x{offset:x}) and length (0x{size:x}) fall outside the total NCA length (0x{baseSize:x}).");
|
||||
@ -693,7 +693,7 @@ namespace LibHac.FsSystem.NcaUtils
|
||||
|
||||
bodyStorage.GetSize(out long baseSize).ThrowIfFailure();
|
||||
|
||||
if (!Utilities.IsSubRange(offset, size, baseSize))
|
||||
if (!IsSubRange(offset, size, baseSize))
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Section offset (0x{offset + 0x400:x}) and length (0x{size:x}) fall outside the total NCA length (0x{baseSize + 0x400:x}).");
|
||||
@ -763,5 +763,11 @@ namespace LibHac.FsSystem.NcaUtils
|
||||
header.CounterType = counterType;
|
||||
header.CounterVersion = counterVersion;
|
||||
}
|
||||
|
||||
private static bool IsSubRange(long startIndex, long subLength, long length)
|
||||
{
|
||||
bool isOutOfRange = startIndex < 0 || startIndex > length || subLength < 0 || startIndex > length - subLength;
|
||||
return !isOutOfRange;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ using LibHac.Common;
|
||||
using LibHac.Crypto;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -121,7 +122,7 @@ namespace LibHac.FsSystem
|
||||
size += entry.NameLength + 1;
|
||||
}
|
||||
|
||||
int endOffset = Utilities.AlignUp(startOffset + size, GetMetaDataAlignment(type));
|
||||
int endOffset = Alignment.AlignUpPow2(startOffset + size, GetMetaDataAlignment(type));
|
||||
return endOffset - startOffset;
|
||||
}
|
||||
|
||||
@ -135,7 +136,7 @@ namespace LibHac.FsSystem
|
||||
}
|
||||
}
|
||||
|
||||
private int GetMetaDataAlignment(PartitionFileSystemType type)
|
||||
private uint GetMetaDataAlignment(PartitionFileSystemType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
@ -5,6 +5,7 @@ using System.Linq;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem.RomFs
|
||||
{
|
||||
@ -61,7 +62,7 @@ namespace LibHac.FsSystem.RomFs
|
||||
Sources.Add(fileStorage);
|
||||
|
||||
long newOffset = CurrentOffset + fileSize;
|
||||
CurrentOffset = Utilities.AlignUp(newOffset, FileAlignment);
|
||||
CurrentOffset = Alignment.AlignUp(newOffset, FileAlignment);
|
||||
|
||||
var padding = new NullStorage(CurrentOffset - newOffset);
|
||||
Sources.Add(padding);
|
||||
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem.RomFs
|
||||
{
|
||||
@ -140,7 +141,7 @@ namespace LibHac.FsSystem.RomFs
|
||||
|
||||
private int CreateNewEntry(int nameLength)
|
||||
{
|
||||
int bytesNeeded = Utilities.AlignUp(_sizeOfEntry + nameLength, 4);
|
||||
int bytesNeeded = Alignment.AlignUp(_sizeOfEntry + nameLength, 4);
|
||||
|
||||
if (_length + bytesNeeded > _capacity)
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem.Save
|
||||
{
|
||||
@ -104,8 +105,8 @@ namespace LibHac.FsSystem.Save
|
||||
|
||||
protected override Result DoSetSize(long size)
|
||||
{
|
||||
int oldBlockCount = (int)Utilities.DivideByRoundUp(_length, BlockSize);
|
||||
int newBlockCount = (int)Utilities.DivideByRoundUp(size, BlockSize);
|
||||
int oldBlockCount = (int)BitUtil.DivideUp(_length, BlockSize);
|
||||
int newBlockCount = (int)BitUtil.DivideUp(size, BlockSize);
|
||||
|
||||
if (oldBlockCount == newBlockCount) return Result.Success;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.IO;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem.Save
|
||||
{
|
||||
@ -64,8 +65,8 @@ namespace LibHac.FsSystem.Save
|
||||
int physicalBlockCount = virtualBlockCount + Header.JournalBlockCount;
|
||||
|
||||
int blockMapLength = virtualBlockCount * MapEntryLength;
|
||||
int physicalBitmapLength = Utilities.AlignUp(physicalBlockCount, 32) / 8;
|
||||
int virtualBitmapLength = Utilities.AlignUp(virtualBlockCount, 32) / 8;
|
||||
int physicalBitmapLength = Alignment.AlignUp(physicalBlockCount, 32) / 8;
|
||||
int virtualBitmapLength = Alignment.AlignUp(virtualBlockCount, 32) / 8;
|
||||
|
||||
MapStorage.Slice(blockMapLength).Fill(SaveDataFileSystem.TrimFillValue);
|
||||
FreeBlocks.Slice(physicalBitmapLength).Fill(SaveDataFileSystem.TrimFillValue);
|
||||
|
@ -3,6 +3,7 @@ using System.Runtime.CompilerServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Fs.Fsa;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem.Save
|
||||
{
|
||||
@ -57,7 +58,7 @@ namespace LibHac.FsSystem.Save
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
int blockCount = (int)Utilities.DivideByRoundUp(size, AllocationTable.Header.BlockSize);
|
||||
int blockCount = (int)BitUtil.DivideUp(size, AllocationTable.Header.BlockSize);
|
||||
int startBlock = AllocationTable.Allocate(blockCount);
|
||||
|
||||
if (startBlock == -1)
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using LibHac.Fs;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac.FsSystem
|
||||
{
|
||||
@ -20,7 +21,7 @@ namespace LibHac.FsSystem
|
||||
|
||||
baseStorage.GetSize(out long baseSize).ThrowIfFailure();
|
||||
|
||||
SectorCount = (int)Utilities.DivideByRoundUp(baseSize, SectorSize);
|
||||
SectorCount = (int)BitUtil.DivideUp(baseSize, SectorSize);
|
||||
Length = baseSize;
|
||||
|
||||
LeaveOpen = leaveOpen;
|
||||
@ -57,7 +58,7 @@ namespace LibHac.FsSystem
|
||||
rc = BaseStorage.GetSize(out long newSize);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
SectorCount = (int)Utilities.DivideByRoundUp(newSize, SectorSize);
|
||||
SectorCount = (int)BitUtil.DivideUp(newSize, SectorSize);
|
||||
Length = newSize;
|
||||
|
||||
return Result.Success;
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using LibHac.Common.Keys;
|
||||
using LibHac.Util;
|
||||
|
||||
namespace LibHac
|
||||
{
|
||||
@ -112,7 +113,7 @@ namespace LibHac
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
long bodyStart = Utilities.GetNextMultiple(4 + sigLength, 0x40);
|
||||
long bodyStart = Alignment.AlignUp(4 + sigLength, 0x40);
|
||||
|
||||
writer.Write((int)SignatureType);
|
||||
|
||||
|
70
src/LibHac/Util/Alignment.cs
Normal file
70
src/LibHac/Util/Alignment.cs
Normal file
@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Diag;
|
||||
|
||||
namespace LibHac.Util
|
||||
{
|
||||
public static class Alignment
|
||||
{
|
||||
// The alignment functions in this class come from C++ templates that always cast to unsigned types
|
||||
|
||||
public static ulong AlignUpPow2(ulong value, uint alignment)
|
||||
{
|
||||
Assert.AssertTrue(BitUtil.IsPowerOfTwo(alignment));
|
||||
|
||||
ulong invMask = alignment - 1;
|
||||
return ((value + invMask) & ~invMask);
|
||||
}
|
||||
|
||||
public static ulong AlignDownPow2(ulong value, uint alignment)
|
||||
{
|
||||
Assert.AssertTrue(BitUtil.IsPowerOfTwo(alignment));
|
||||
|
||||
ulong invMask = alignment - 1;
|
||||
return (value & ~invMask);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
public static bool IsAlignedPow2(ulong value, uint alignment)
|
||||
{
|
||||
Assert.AssertTrue(BitUtil.IsPowerOfTwo(alignment));
|
||||
|
||||
ulong invMask = alignment - 1;
|
||||
return (value & invMask) == 0;
|
||||
}
|
||||
|
||||
public static bool IsAlignedPow2<T>(Span<T> buffer, uint alignment)
|
||||
{
|
||||
return IsAlignedPow2(buffer, alignment);
|
||||
}
|
||||
|
||||
public static bool IsAlignedPow2<T>(ReadOnlySpan<T> buffer, uint alignment)
|
||||
{
|
||||
return IsAlignedPow2(ref MemoryMarshal.GetReference(buffer), alignment);
|
||||
}
|
||||
|
||||
public static unsafe bool IsAlignedPow2<T>(ref T pointer, uint alignment)
|
||||
{
|
||||
return IsAlignedPow2((ulong)Unsafe.AsPointer(ref pointer), alignment);
|
||||
}
|
||||
|
||||
public static int AlignUpPow2(int value, uint alignment) => (int)AlignUpPow2((ulong)value, alignment);
|
||||
public static long AlignUpPow2(long value, uint alignment) => (long)AlignUpPow2((ulong)value, alignment);
|
||||
public static int AlignDownPow2(int value, uint alignment) => (int)AlignDownPow2((ulong)value, alignment);
|
||||
public static long AlignDownPow2(long value, uint alignment) => (long)AlignDownPow2((ulong)value, alignment);
|
||||
public static bool IsAlignedPow2(int value, uint alignment) => IsAlignedPow2((ulong)value, alignment);
|
||||
public static bool IsAlignedPow2(long value, uint alignment) => IsAlignedPow2((ulong)value, alignment);
|
||||
|
||||
public static ulong AlignUp(ulong value, uint alignment) => AlignDown(value + alignment - 1, alignment);
|
||||
public static ulong AlignDown(ulong value, uint alignment) => value - value % alignment;
|
||||
public static bool IsAligned(ulong value, uint alignment) => value % alignment == 0;
|
||||
|
||||
public static int AlignUp(int value, uint alignment) => (int)AlignUp((ulong)value, alignment);
|
||||
public static long AlignUp(long value, uint alignment) => (long)AlignUp((ulong)value, alignment);
|
||||
public static int AlignDown(int value, uint alignment) => (int)AlignDown((ulong)value, alignment);
|
||||
public static long AlignDown(long value, uint alignment) => (long)AlignDown((ulong)value, alignment);
|
||||
public static bool IsAligned(int value, uint alignment) => IsAligned((ulong)value, alignment);
|
||||
public static bool IsAligned(long value, uint alignment) => IsAligned((ulong)value, alignment);
|
||||
}
|
||||
}
|
46
src/LibHac/Util/BitUtil.cs
Normal file
46
src/LibHac/Util/BitUtil.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace LibHac.Util
|
||||
{
|
||||
public static class BitUtil
|
||||
{
|
||||
public static bool IsPowerOfTwo(int value)
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPowerOfTwo(long value)
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool IsPowerOfTwo(ulong value)
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
}
|
||||
|
||||
private static int ResetLeastSignificantOneBit(int value)
|
||||
{
|
||||
return value & (value - 1);
|
||||
}
|
||||
|
||||
private static long ResetLeastSignificantOneBit(long value)
|
||||
{
|
||||
return value & (value - 1);
|
||||
}
|
||||
|
||||
private static ulong ResetLeastSignificantOneBit(ulong value)
|
||||
{
|
||||
return value & (value - 1);
|
||||
}
|
||||
|
||||
// DivideUp comes from a C++ template that always casts to unsigned types
|
||||
public static uint DivideUp(uint value, uint divisor) => (value + divisor - 1) / divisor;
|
||||
public static ulong DivideUp(ulong value, ulong divisor) => (value + divisor - 1) / divisor;
|
||||
|
||||
public static int DivideUp(int value, int divisor) => (int)DivideUp((uint)value, (uint)divisor);
|
||||
public static long DivideUp(long value, long divisor) => (long)DivideUp((ulong)value, (ulong)divisor);
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
@ -11,35 +10,6 @@ namespace LibHac
|
||||
{
|
||||
private const int MediaSize = 0x200;
|
||||
|
||||
public static byte[][] CreateJaggedByteArray(int len1, int len2)
|
||||
{
|
||||
var array = new byte[len1][];
|
||||
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = new byte[len2];
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public static byte[][][] CreateJaggedByteArray(int len1, int len2, int len3)
|
||||
{
|
||||
var array = new byte[len1][][];
|
||||
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
array[i] = new byte[len2][];
|
||||
|
||||
for (int j = 0; j < array[i].Length; j++)
|
||||
{
|
||||
array[i][j] = new byte[len3];
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public static bool ArraysEqual<T>(T[] a1, T[] a2)
|
||||
{
|
||||
if (a1 == null || a2 == null) return false;
|
||||
@ -265,26 +235,7 @@ namespace LibHac
|
||||
// Return formatted number with suffix
|
||||
return readable.ToString("0.### ") + suffix;
|
||||
}
|
||||
|
||||
public static long GetNextMultiple(long value, int multiple)
|
||||
{
|
||||
if (multiple <= 0)
|
||||
return value;
|
||||
|
||||
if (value % multiple == 0)
|
||||
return value;
|
||||
|
||||
return value + multiple - value % multiple;
|
||||
}
|
||||
|
||||
public static int DivideByRoundUp(int value, int divisor) => (value + divisor - 1) / divisor;
|
||||
public static long DivideByRoundUp(long value, long divisor) => (value + divisor - 1) / divisor;
|
||||
|
||||
public static int AlignUp(int value, int multiple) => AlignDown(value + multiple - 1, multiple);
|
||||
public static long AlignUp(long value, long multiple) => AlignDown(value + multiple - 1, multiple);
|
||||
public static int AlignDown(int value, int multiple) => value - value % multiple;
|
||||
public static long AlignDown(long value, long multiple) => value - value % multiple;
|
||||
|
||||
|
||||
public static void IncrementByteArray(byte[] array)
|
||||
{
|
||||
for (int i = array.Length - 1; i >= 0; i--)
|
||||
@ -341,100 +292,11 @@ namespace LibHac
|
||||
_ => "Unknown"
|
||||
};
|
||||
|
||||
public static bool IsSubRange(long startIndex, long subLength, long length)
|
||||
{
|
||||
bool isOutOfRange = startIndex < 0 || startIndex > length || subLength < 0 || startIndex > length - subLength;
|
||||
return !isOutOfRange;
|
||||
}
|
||||
|
||||
public static int GetMasterKeyRevision(int keyGeneration)
|
||||
{
|
||||
if (keyGeneration == 0) return 0;
|
||||
|
||||
return keyGeneration - 1;
|
||||
}
|
||||
|
||||
public static bool IsPowerOfTwo(int value)
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
}
|
||||
|
||||
public static bool IsPowerOfTwo(long value)
|
||||
{
|
||||
return value > 0 && ResetLeastSignificantOneBit(value) == 0;
|
||||
}
|
||||
|
||||
public static BigInteger GetBigInteger(this ReadOnlySpan<byte> bytes)
|
||||
{
|
||||
var signPadded = new byte[bytes.Length + 1];
|
||||
bytes.CopyTo(signPadded.AsSpan(1));
|
||||
Array.Reverse(signPadded);
|
||||
return new BigInteger(signPadded);
|
||||
}
|
||||
|
||||
public static byte[] GetBytes(this BigInteger value, int size)
|
||||
{
|
||||
byte[] bytes = value.ToByteArray();
|
||||
|
||||
if (size == -1)
|
||||
{
|
||||
size = bytes.Length;
|
||||
}
|
||||
|
||||
if (bytes.Length > size + 1)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
|
||||
}
|
||||
|
||||
if (bytes.Length == size + 1 && bytes[bytes.Length - 1] != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Cannot squeeze value {value} to {size} bytes from {bytes.Length}.");
|
||||
}
|
||||
|
||||
Array.Resize(ref bytes, size);
|
||||
Array.Reverse(bytes);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static BigInteger ModInverse(BigInteger e, BigInteger n)
|
||||
{
|
||||
BigInteger r = n;
|
||||
BigInteger newR = e;
|
||||
BigInteger t = 0;
|
||||
BigInteger newT = 1;
|
||||
|
||||
while (newR != 0)
|
||||
{
|
||||
BigInteger quotient = r / newR;
|
||||
BigInteger temp;
|
||||
|
||||
temp = t;
|
||||
t = newT;
|
||||
newT = temp - quotient * newT;
|
||||
|
||||
temp = r;
|
||||
r = newR;
|
||||
newR = temp - quotient * newR;
|
||||
}
|
||||
|
||||
if (t < 0)
|
||||
{
|
||||
t = t + n;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static int ResetLeastSignificantOneBit(int value)
|
||||
{
|
||||
return value & (value - 1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static long ResetLeastSignificantOneBit(long value)
|
||||
{
|
||||
return value & (value - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user