diff options
Diffstat (limited to 'ARMeilleure/Memory/MemoryManager.cs')
-rw-r--r-- | ARMeilleure/Memory/MemoryManager.cs | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/ARMeilleure/Memory/MemoryManager.cs b/ARMeilleure/Memory/MemoryManager.cs index f813bd7e..e4e8b2d2 100644 --- a/ARMeilleure/Memory/MemoryManager.cs +++ b/ARMeilleure/Memory/MemoryManager.cs @@ -1,6 +1,7 @@ using ARMeilleure.State; using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; @@ -552,6 +553,50 @@ namespace ARMeilleure.Memory return data; } + public ReadOnlySpan<byte> GetSpan(ulong address, ulong size) + { + if (IsContiguous(address, size)) + { + return new ReadOnlySpan<byte>((void*)Translate((long)address), (int)size); + } + else + { + return ReadBytes((long)address, (long)size); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private bool IsContiguous(ulong address, ulong size) + { + if (!IsValidPosition((long)address)) + { + return false; + } + + ulong endVa = (address + size + PageMask) & ~(ulong)PageMask; + + address &= ~(ulong)PageMask; + + int pages = (int)((endVa - address) / PageSize); + + for (int page = 0; page < pages - 1; page++) + { + if (!IsValidPosition((long)address + PageSize)) + { + return false; + } + + if (GetPtEntry((long)address) + PageSize != GetPtEntry((long)address + PageSize)) + { + return false; + } + + address += PageSize; + } + + return true; + } + public void WriteSByte(long position, sbyte value) { WriteByte(position, (byte)value); |