Enable full memory checking on all memory accesses
This commit is contained in:
parent
be0e4007dc
commit
b8fd849247
20 changed files with 499 additions and 380 deletions
|
@ -41,9 +41,9 @@ namespace ChocolArm64.Memory
|
|||
|
||||
private byte* RamPtr;
|
||||
|
||||
public AMemory(IntPtr Ram)
|
||||
public AMemory(IntPtr Ram, long RamSize, int AddressSpaceBits)
|
||||
{
|
||||
Manager = new AMemoryMgr();
|
||||
Manager = new AMemoryMgr(RamSize, AddressSpaceBits);
|
||||
|
||||
Monitors = new Dictionary<int, ExMonitor>();
|
||||
|
||||
|
@ -142,90 +142,121 @@ namespace ChocolArm64.Memory
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte ReadByte(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
byte* Ptr = RamPtr + Position;
|
||||
|
||||
return *((byte*)(RamPtr + (uint)Position));
|
||||
if (Manager.IsDirectRead(Position))
|
||||
{
|
||||
return *Ptr;
|
||||
}
|
||||
|
||||
return ReadByteSlow(Position);
|
||||
}
|
||||
|
||||
private byte ReadByteSlow(long Position)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
return *(RamPtr + PA);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ushort ReadUInt16(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
ushort* Ptr = (ushort*)(RamPtr + Position);
|
||||
|
||||
return *((ushort*)(RamPtr + (uint)Position));
|
||||
if (Manager.IsDirectRead(Position))
|
||||
{
|
||||
return *Ptr;
|
||||
}
|
||||
|
||||
throw new VmmPageFaultException(Position);
|
||||
}
|
||||
|
||||
private ushort ReadUInt16Slow(long Position)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
EnsureAccessIsValid(Position + 1, AMemoryPerm.Read);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
return *((ushort*)(RamPtr + PA));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint ReadUInt32(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
uint* Ptr = (uint*)(RamPtr + Position);
|
||||
|
||||
return *((uint*)(RamPtr + (uint)Position));
|
||||
if (Manager.IsDirectRead(Position))
|
||||
{
|
||||
return *Ptr;
|
||||
}
|
||||
|
||||
return ReadUInt32Slow(Position);
|
||||
}
|
||||
|
||||
private uint ReadUInt32Slow(long Position)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
EnsureAccessIsValid(Position + 3, AMemoryPerm.Read);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
return *((uint*)(RamPtr + PA));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong ReadUInt64(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
ulong* Ptr = (ulong*)(RamPtr + Position);
|
||||
|
||||
return *((ulong*)(RamPtr + (uint)Position));
|
||||
if (Manager.IsDirectRead(Position))
|
||||
{
|
||||
return *Ptr;
|
||||
}
|
||||
|
||||
return ReadUInt64Slow(Position);
|
||||
}
|
||||
|
||||
private ulong ReadUInt64Slow(long Position)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
EnsureAccessIsValid(Position + 7, AMemoryPerm.Read);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
return *((ulong*)(RamPtr + PA));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public AVec ReadVector8(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
|
||||
return new AVec() { B0 = ReadByte(Position) };
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public AVec ReadVector16(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
|
||||
return new AVec() { H0 = ReadUInt16(Position) };
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public AVec ReadVector32(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
|
||||
return new AVec() { W0 = ReadUInt32(Position) };
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public AVec ReadVector64(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
|
||||
return new AVec() { X0 = ReadUInt64(Position) };
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public AVec ReadVector128(long Position)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||
#endif
|
||||
|
||||
return new AVec()
|
||||
{
|
||||
X0 = ReadUInt64(Position + 0),
|
||||
|
@ -241,94 +272,161 @@ namespace ChocolArm64.Memory
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteByte(long Position, byte Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
byte* Ptr = RamPtr + Position;
|
||||
|
||||
*((byte*)(RamPtr + (uint)Position)) = Value;
|
||||
if (Manager.IsDirectWrite(Position))
|
||||
{
|
||||
*Ptr = Value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
WriteByteSlow(Position, Value);
|
||||
}
|
||||
|
||||
private void WriteByteSlow(long Position, byte Value)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
*(RamPtr + PA) = Value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUInt16(long Position, ushort Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
ushort* Ptr = (ushort*)(RamPtr + Position);
|
||||
|
||||
*((ushort*)(RamPtr + (uint)Position)) = Value;
|
||||
if (Manager.IsDirectWrite(Position))
|
||||
{
|
||||
*Ptr = Value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
WriteUInt16Slow(Position, Value);
|
||||
}
|
||||
|
||||
private void WriteUInt16Slow(long Position, ushort Value)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
EnsureAccessIsValid(Position + 1, AMemoryPerm.Write);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
*((ushort*)(RamPtr + PA)) = Value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUInt32(long Position, uint Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
uint* Ptr = (uint*)(RamPtr + Position);
|
||||
|
||||
*((uint*)(RamPtr + (uint)Position)) = Value;
|
||||
if (Manager.IsDirectWrite(Position))
|
||||
{
|
||||
*Ptr = Value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
WriteUInt32Slow(Position, Value);
|
||||
}
|
||||
|
||||
private void WriteUInt32Slow(long Position, uint Value)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
EnsureAccessIsValid(Position + 3, AMemoryPerm.Write);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
*((uint*)(RamPtr + PA)) = Value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUInt64(long Position, ulong Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
ulong* Ptr = (ulong*)(RamPtr + Position);
|
||||
|
||||
*((ulong*)(RamPtr + (uint)Position)) = Value;
|
||||
if (Manager.IsDirectWrite(Position))
|
||||
{
|
||||
*Ptr = Value;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
WriteUInt64Slow(Position, Value);
|
||||
}
|
||||
|
||||
private void WriteUInt64Slow(long Position, ulong Value)
|
||||
{
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
EnsureAccessIsValid(Position + 7, AMemoryPerm.Write);
|
||||
|
||||
long PA = Manager.TranslatePosition(Position);
|
||||
|
||||
*((ulong*)(RamPtr + PA)) = Value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteVector8(long Position, AVec Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
|
||||
WriteByte(Position, Value.B0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteVector16(long Position, AVec Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
|
||||
WriteUInt16(Position, Value.H0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteVector32(long Position, AVec Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
|
||||
WriteUInt32(Position, Value.W0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteVector64(long Position, AVec Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
|
||||
WriteUInt64(Position, Value.X0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteVector128(long Position, AVec Value)
|
||||
{
|
||||
#if DEBUG
|
||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||
#endif
|
||||
|
||||
WriteUInt64(Position + 0, Value.X0);
|
||||
WriteUInt64(Position + 8, Value.X1);
|
||||
}
|
||||
|
||||
public void WriteDirectUnchecked(long Position, byte[] Data)
|
||||
{
|
||||
byte* Ptr = (byte*)(RamPtr + Position);
|
||||
|
||||
int Pages = (Data.Length + AMemoryMgr.PageMask) / AMemoryMgr.PageSize;
|
||||
|
||||
int RemSize = Data.Length;
|
||||
|
||||
for (int Page = 0; Page < Pages; Page++)
|
||||
{
|
||||
int Offset = Page * AMemoryMgr.PageSize;
|
||||
|
||||
if (!Manager.IsMapped(Position + Offset))
|
||||
{
|
||||
throw new VmmPageFaultException(Position + Offset);
|
||||
}
|
||||
|
||||
int ToCopy = Math.Min(AMemoryMgr.PageSize, RemSize);
|
||||
|
||||
for (; Offset < Page * AMemoryMgr.PageSize + ToCopy; Offset++)
|
||||
{
|
||||
*Ptr++ = Data[Offset];
|
||||
}
|
||||
|
||||
RemSize -= AMemoryMgr.PageSize;
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureAccessIsValid(long Position, AMemoryPerm Perm)
|
||||
{
|
||||
if (!Manager.IsMapped(Position))
|
||||
|
|
|
@ -4,28 +4,41 @@ namespace ChocolArm64.Memory
|
|||
{
|
||||
public class AMemoryMgr
|
||||
{
|
||||
public const long AddrSize = RamSize;
|
||||
public const long RamSize = 4L * 1024 * 1024 * 1024;
|
||||
private ulong RamSize;
|
||||
|
||||
private ulong AddressSpaceSize;
|
||||
|
||||
private int PTLvl0Bits;
|
||||
private int PTLvl1Bits;
|
||||
|
||||
private int PTLvl0Size;
|
||||
private int PTLvl1Size;
|
||||
|
||||
private int PTLvl0Mask;
|
||||
private int PTLvl1Mask;
|
||||
|
||||
private int PTLvl0Bit;
|
||||
|
||||
private const int PTLvl0Bits = 10;
|
||||
private const int PTLvl1Bits = 10;
|
||||
private const int PTPageBits = 12;
|
||||
|
||||
private const int PTLvl0Size = 1 << PTLvl0Bits;
|
||||
private const int PTLvl1Size = 1 << PTLvl1Bits;
|
||||
public const int PageSize = 1 << PTPageBits;
|
||||
public const int PageSize = 1 << PTPageBits;
|
||||
|
||||
private const int PTLvl0Mask = PTLvl0Size - 1;
|
||||
private const int PTLvl1Mask = PTLvl1Size - 1;
|
||||
public const int PageMask = PageSize - 1;
|
||||
public const int PageMask = PageSize - 1;
|
||||
|
||||
private const int PTLvl0Bit = PTPageBits + PTLvl1Bits;
|
||||
private const int PTLvl1Bit = PTPageBits;
|
||||
private const int PTLvl1Bit = PTPageBits;
|
||||
|
||||
private enum PTMap
|
||||
private enum PTMap : byte
|
||||
{
|
||||
Unmapped,
|
||||
Mapped
|
||||
Unmapped = 0,
|
||||
Mapped = 1,
|
||||
|
||||
Direct = 1 << 5,
|
||||
DirectRead = Direct | 1 << 6,
|
||||
DirectWrite = Direct | 1 << 7,
|
||||
|
||||
DirectRW =
|
||||
DirectRead |
|
||||
DirectWrite
|
||||
}
|
||||
|
||||
private struct PTEntry
|
||||
|
@ -33,38 +46,121 @@ namespace ChocolArm64.Memory
|
|||
public PTMap Map;
|
||||
public AMemoryPerm Perm;
|
||||
|
||||
public long Position;
|
||||
public int Type;
|
||||
public int Attr;
|
||||
|
||||
public PTEntry(PTMap Map, AMemoryPerm Perm, int Type, int Attr)
|
||||
public PTEntry(PTMap Map, long Position, AMemoryPerm Perm, int Type, int Attr)
|
||||
{
|
||||
this.Map = Map;
|
||||
this.Position = Position;
|
||||
this.Perm = Perm;
|
||||
this.Type = Type;
|
||||
this.Attr = Attr;
|
||||
}
|
||||
}
|
||||
|
||||
private PTMap[] MapTypes;
|
||||
|
||||
private PTEntry[][] PageTable;
|
||||
|
||||
public AMemoryMgr()
|
||||
public AMemoryMgr(long RamSize, int AddressSpaceBits)
|
||||
{
|
||||
this.RamSize = (ulong)RamSize;
|
||||
|
||||
AddressSpaceSize = 1UL << AddressSpaceBits;
|
||||
|
||||
int RemBits = AddressSpaceBits - PTPageBits;
|
||||
|
||||
PTLvl0Bits = RemBits >> 1;
|
||||
PTLvl1Bits = RemBits - PTLvl0Bits;
|
||||
|
||||
PTLvl0Size = 1 << PTLvl0Bits;
|
||||
PTLvl1Size = 1 << PTLvl1Bits;
|
||||
|
||||
PTLvl0Mask = PTLvl0Size - 1;
|
||||
PTLvl1Mask = PTLvl1Size - 1;
|
||||
|
||||
PTLvl0Bit = PTPageBits + PTLvl1Bits;
|
||||
|
||||
MapTypes = new PTMap[1 << RemBits];
|
||||
|
||||
PageTable = new PTEntry[PTLvl0Size][];
|
||||
}
|
||||
|
||||
public void Map(long Position, long Size, int Type, AMemoryPerm Perm)
|
||||
public void MapDirectRX(long Position, long Size, int Type)
|
||||
{
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.Mapped, Perm, Type, 0));
|
||||
if ((ulong)Position >= RamSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Position));
|
||||
}
|
||||
|
||||
if ((ulong)(Position + Size) > RamSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||
}
|
||||
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.DirectRead, 0, AMemoryPerm.RX, Type, 0));
|
||||
}
|
||||
|
||||
public void MapDirectRO(long Position, long Size, int Type)
|
||||
{
|
||||
if ((ulong)Position >= RamSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Position));
|
||||
}
|
||||
|
||||
if ((ulong)(Position + Size) > RamSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||
}
|
||||
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.DirectRead, 0, AMemoryPerm.Read, Type, 0));
|
||||
}
|
||||
|
||||
public void MapDirectRW(long Position, long Size, int Type)
|
||||
{
|
||||
if ((ulong)Position >= RamSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Position));
|
||||
}
|
||||
|
||||
if ((ulong)(Position + Size) > RamSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||
}
|
||||
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.DirectRW, 0, AMemoryPerm.RW, Type, 0));
|
||||
}
|
||||
|
||||
public void Map(long VA, long PA, long Size, int Type, AMemoryPerm Perm)
|
||||
{
|
||||
if ((ulong)VA >= AddressSpaceSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(VA));
|
||||
}
|
||||
|
||||
if ((ulong)PA >= RamSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(PA));
|
||||
}
|
||||
|
||||
if ((ulong)(PA + Size) > RamSize || (ulong)(VA + Size) > AddressSpaceSize)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(Size));
|
||||
}
|
||||
|
||||
SetPTEntry(VA, Size, new PTEntry(PTMap.Mapped, PA, Perm, Type, 0));
|
||||
}
|
||||
|
||||
public void Unmap(long Position, long Size)
|
||||
{
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 0));
|
||||
SetPTEntry(Position, Size, new PTEntry(PTMap.Unmapped, 0, 0, 0, 0));
|
||||
}
|
||||
|
||||
public void Unmap(long Position, long Size, int Type)
|
||||
{
|
||||
SetPTEntry(Position, Size, Type, new PTEntry(PTMap.Unmapped, 0, 0, 0));
|
||||
SetPTEntry(Position, Size, Type, new PTEntry(PTMap.Unmapped, 0, 0, 0, 0));
|
||||
}
|
||||
|
||||
public void Reprotect(long Position, long Size, AMemoryPerm Perm)
|
||||
|
@ -121,7 +217,7 @@ namespace ChocolArm64.Memory
|
|||
Start -= PageSize;
|
||||
}
|
||||
|
||||
while (End < AddrSize && IsSameSegment(End))
|
||||
while ((ulong)End < AddressSpaceSize && IsSameSegment(End))
|
||||
{
|
||||
End += PageSize;
|
||||
}
|
||||
|
@ -199,6 +295,35 @@ namespace ChocolArm64.Memory
|
|||
return PageTable[L0][L1].Map != PTMap.Unmapped;
|
||||
}
|
||||
|
||||
public long TranslatePosition(long Position)
|
||||
{
|
||||
if (IsDirect(Position))
|
||||
{
|
||||
return Position;
|
||||
}
|
||||
else
|
||||
{
|
||||
long BasePosition = GetPTEntry(Position).Position;
|
||||
|
||||
return BasePosition + (Position & AMemoryMgr.PageMask);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsDirect(long Position)
|
||||
{
|
||||
return (MapTypes[(ulong)Position >> PTPageBits] & PTMap.Direct) != 0;
|
||||
}
|
||||
|
||||
public bool IsDirectRead(long Position)
|
||||
{
|
||||
return (MapTypes[(ulong)Position >> PTPageBits] & PTMap.DirectRead) != 0;
|
||||
}
|
||||
|
||||
public bool IsDirectWrite(long Position)
|
||||
{
|
||||
return (MapTypes[(ulong)Position >> PTPageBits] & PTMap.DirectWrite) != 0;
|
||||
}
|
||||
|
||||
private PTEntry GetPTEntry(long Position)
|
||||
{
|
||||
long L0 = (Position >> PTLvl0Bit) & PTLvl0Mask;
|
||||
|
@ -214,10 +339,14 @@ namespace ChocolArm64.Memory
|
|||
|
||||
private void SetPTEntry(long Position, long Size, PTEntry Entry)
|
||||
{
|
||||
Entry.Position &= ~PageMask;
|
||||
|
||||
while (Size > 0)
|
||||
{
|
||||
SetPTEntry(Position, Entry);
|
||||
|
||||
Entry.Position += PageSize;
|
||||
|
||||
Position += PageSize;
|
||||
Size -= PageSize;
|
||||
}
|
||||
|
@ -225,12 +354,13 @@ namespace ChocolArm64.Memory
|
|||
|
||||
private void SetPTEntry(long Position, long Size, int Type, PTEntry Entry)
|
||||
{
|
||||
while (Size > 0)
|
||||
Entry.Position &= ~PageMask;
|
||||
|
||||
while (Size > 0 && GetPTEntry(Position).Type == Type)
|
||||
{
|
||||
if (GetPTEntry(Position).Type == Type)
|
||||
{
|
||||
SetPTEntry(Position, Entry);
|
||||
}
|
||||
SetPTEntry(Position, Entry);
|
||||
|
||||
Entry.Position += PageSize;
|
||||
|
||||
Position += PageSize;
|
||||
Size -= PageSize;
|
||||
|
@ -253,6 +383,8 @@ namespace ChocolArm64.Memory
|
|||
}
|
||||
|
||||
PageTable[L0][L1] = Entry;
|
||||
|
||||
MapTypes[Position >> PTPageBits] = Entry.Map;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ using System;
|
|||
namespace ChocolArm64.Memory
|
||||
{
|
||||
[Flags]
|
||||
public enum AMemoryPerm
|
||||
public enum AMemoryPerm : byte
|
||||
{
|
||||
None = 0,
|
||||
Read = 1 << 0,
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Core.OsHle.Handles;
|
||||
using System;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Ryujinx.Core.Input
|
||||
|
@ -62,51 +60,16 @@ namespace Ryujinx.Core.Input
|
|||
|
||||
private const int HidEntryCount = 17;
|
||||
|
||||
private object ShMemLock;
|
||||
|
||||
private long[] ShMemPositions;
|
||||
|
||||
private IntPtr Ram;
|
||||
|
||||
public Hid(IntPtr Ram)
|
||||
public long PA { get; private set; }
|
||||
|
||||
public Hid(IntPtr Ram, long PA)
|
||||
{
|
||||
this.Ram = Ram;
|
||||
this.PA = PA;
|
||||
|
||||
ShMemLock = new object();
|
||||
|
||||
ShMemPositions = new long[0];
|
||||
}
|
||||
|
||||
internal void ShMemMap(object sender, EventArgs e)
|
||||
{
|
||||
HSharedMem SharedMem = (HSharedMem)sender;
|
||||
|
||||
lock (ShMemLock)
|
||||
{
|
||||
ShMemPositions = SharedMem.GetVirtualPositions();
|
||||
|
||||
long BasePosition = ShMemPositions[ShMemPositions.Length - 1];
|
||||
|
||||
Logging.Info($"HID shared memory successfully mapped to 0x{BasePosition:x16}!");
|
||||
|
||||
Init(BasePosition);
|
||||
}
|
||||
}
|
||||
|
||||
internal void ShMemUnmap(object sender, EventArgs e)
|
||||
{
|
||||
HSharedMem SharedMem = (HSharedMem)sender;
|
||||
|
||||
lock (ShMemLock)
|
||||
{
|
||||
ShMemPositions = SharedMem.GetVirtualPositions();
|
||||
}
|
||||
}
|
||||
|
||||
private void Init(long BasePosition)
|
||||
{
|
||||
InitializeJoyconPair(
|
||||
BasePosition,
|
||||
JoyConColor.Body_Neon_Red,
|
||||
JoyConColor.Buttons_Neon_Red,
|
||||
JoyConColor.Body_Neon_Blue,
|
||||
|
@ -114,13 +77,12 @@ namespace Ryujinx.Core.Input
|
|||
}
|
||||
|
||||
private void InitializeJoyconPair(
|
||||
long BasePosition,
|
||||
JoyConColor LeftColorBody,
|
||||
JoyConColor LeftColorButtons,
|
||||
JoyConColor RightColorBody,
|
||||
JoyConColor RightColorButtons)
|
||||
{
|
||||
long BaseControllerOffset = BasePosition + HidControllersOffset + 8 * HidControllerSize;
|
||||
long BaseControllerOffset = HidControllersOffset + 8 * HidControllerSize;
|
||||
|
||||
HidControllerType Type =
|
||||
HidControllerType.ControllerType_Handheld |
|
||||
|
@ -159,123 +121,105 @@ namespace Ryujinx.Core.Input
|
|||
HidJoystickPosition LeftStick,
|
||||
HidJoystickPosition RightStick)
|
||||
{
|
||||
lock (ShMemLock)
|
||||
{
|
||||
foreach (long Position in ShMemPositions)
|
||||
{
|
||||
long ControllerOffset = Position + HidControllersOffset;
|
||||
long ControllerOffset = HidControllersOffset;
|
||||
|
||||
ControllerOffset += (int)ControllerId * HidControllerSize;
|
||||
ControllerOffset += (int)ControllerId * HidControllerSize;
|
||||
|
||||
ControllerOffset += HidControllerHeaderSize;
|
||||
ControllerOffset += HidControllerHeaderSize;
|
||||
|
||||
ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
|
||||
ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
|
||||
|
||||
long LastEntry = ReadInt64(ControllerOffset + 0x10);
|
||||
long LastEntry = ReadInt64(ControllerOffset + 0x10);
|
||||
|
||||
long CurrEntry = (LastEntry + 1) % HidEntryCount;
|
||||
long CurrEntry = (LastEntry + 1) % HidEntryCount;
|
||||
|
||||
long Timestamp = Stopwatch.GetTimestamp();
|
||||
long Timestamp = Stopwatch.GetTimestamp();
|
||||
|
||||
WriteInt64(ControllerOffset + 0x0, Timestamp);
|
||||
WriteInt64(ControllerOffset + 0x8, HidEntryCount);
|
||||
WriteInt64(ControllerOffset + 0x10, CurrEntry);
|
||||
WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
|
||||
WriteInt64(ControllerOffset + 0x0, Timestamp);
|
||||
WriteInt64(ControllerOffset + 0x8, HidEntryCount);
|
||||
WriteInt64(ControllerOffset + 0x10, CurrEntry);
|
||||
WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
|
||||
|
||||
ControllerOffset += HidControllersLayoutHeaderSize;
|
||||
ControllerOffset += HidControllersLayoutHeaderSize;
|
||||
|
||||
ControllerOffset += CurrEntry * HidControllersInputEntrySize;
|
||||
ControllerOffset += CurrEntry * HidControllersInputEntrySize;
|
||||
|
||||
WriteInt64(ControllerOffset + 0x0, Timestamp);
|
||||
WriteInt64(ControllerOffset + 0x8, Timestamp);
|
||||
WriteInt64(ControllerOffset + 0x0, Timestamp);
|
||||
WriteInt64(ControllerOffset + 0x8, Timestamp);
|
||||
|
||||
WriteInt64(ControllerOffset + 0x10, (uint)Buttons);
|
||||
WriteInt64(ControllerOffset + 0x10, (uint)Buttons);
|
||||
|
||||
WriteInt32(ControllerOffset + 0x18, LeftStick.DX);
|
||||
WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
|
||||
WriteInt32(ControllerOffset + 0x18, LeftStick.DX);
|
||||
WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
|
||||
|
||||
WriteInt64(ControllerOffset + 0x20, RightStick.DX);
|
||||
WriteInt64(ControllerOffset + 0x24, RightStick.DY);
|
||||
WriteInt64(ControllerOffset + 0x20, RightStick.DX);
|
||||
WriteInt64(ControllerOffset + 0x24, RightStick.DY);
|
||||
|
||||
WriteInt64(ControllerOffset + 0x28,
|
||||
(uint)HidControllerConnState.Controller_State_Connected |
|
||||
(uint)HidControllerConnState.Controller_State_Wired);
|
||||
}
|
||||
}
|
||||
WriteInt64(ControllerOffset + 0x28,
|
||||
(uint)HidControllerConnState.Controller_State_Connected |
|
||||
(uint)HidControllerConnState.Controller_State_Wired);
|
||||
}
|
||||
|
||||
public void SetTouchPoints(params HidTouchPoint[] Points)
|
||||
{
|
||||
lock (ShMemLock)
|
||||
long TouchScreenOffset = HidTouchScreenOffset;
|
||||
|
||||
long LastEntry = ReadInt64(TouchScreenOffset + 0x10);
|
||||
|
||||
long CurrEntry = (LastEntry + 1) % HidEntryCount;
|
||||
|
||||
long Timestamp = ReadInt64(TouchScreenOffset) + 1;
|
||||
|
||||
WriteInt64(TouchScreenOffset + 0x0, Timestamp);
|
||||
WriteInt64(TouchScreenOffset + 0x8, HidEntryCount);
|
||||
WriteInt64(TouchScreenOffset + 0x10, CurrEntry);
|
||||
WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1);
|
||||
WriteInt64(TouchScreenOffset + 0x20, Timestamp);
|
||||
|
||||
long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
|
||||
|
||||
long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
|
||||
|
||||
TouchEntryOffset += CurrEntry * HidTouchEntrySize;
|
||||
|
||||
WriteInt64(TouchEntryOffset + 0x0, Timestamp);
|
||||
WriteInt64(TouchEntryOffset + 0x8, Points.Length);
|
||||
|
||||
TouchEntryOffset += HidTouchEntryHeaderSize;
|
||||
|
||||
const int Padding = 0;
|
||||
|
||||
int Index = 0;
|
||||
|
||||
foreach (HidTouchPoint Point in Points)
|
||||
{
|
||||
foreach (long Position in ShMemPositions)
|
||||
{
|
||||
long TouchScreenOffset = Position + HidTouchScreenOffset;
|
||||
WriteInt64(TouchEntryOffset + 0x0, Timestamp);
|
||||
WriteInt32(TouchEntryOffset + 0x8, Padding);
|
||||
WriteInt32(TouchEntryOffset + 0xc, Index++);
|
||||
WriteInt32(TouchEntryOffset + 0x10, Point.X);
|
||||
WriteInt32(TouchEntryOffset + 0x14, Point.Y);
|
||||
WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX);
|
||||
WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY);
|
||||
WriteInt32(TouchEntryOffset + 0x20, Point.Angle);
|
||||
WriteInt32(TouchEntryOffset + 0x24, Padding);
|
||||
|
||||
long LastEntry = ReadInt64(TouchScreenOffset + 0x10);
|
||||
|
||||
long CurrEntry = (LastEntry + 1) % HidEntryCount;
|
||||
|
||||
long Timestamp = ReadInt64(TouchScreenOffset) + 1;
|
||||
|
||||
WriteInt64(TouchScreenOffset + 0x0, Timestamp);
|
||||
WriteInt64(TouchScreenOffset + 0x8, HidEntryCount);
|
||||
WriteInt64(TouchScreenOffset + 0x10, CurrEntry);
|
||||
WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1);
|
||||
WriteInt64(TouchScreenOffset + 0x20, Timestamp);
|
||||
|
||||
long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
|
||||
|
||||
long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
|
||||
|
||||
TouchEntryOffset += CurrEntry * HidTouchEntrySize;
|
||||
|
||||
WriteInt64(TouchEntryOffset + 0x0, Timestamp);
|
||||
WriteInt64(TouchEntryOffset + 0x8, Points.Length);
|
||||
|
||||
TouchEntryOffset += HidTouchEntryHeaderSize;
|
||||
|
||||
const int Padding = 0;
|
||||
|
||||
int Index = 0;
|
||||
|
||||
foreach (HidTouchPoint Point in Points)
|
||||
{
|
||||
WriteInt64(TouchEntryOffset + 0x0, Timestamp);
|
||||
WriteInt32(TouchEntryOffset + 0x8, Padding);
|
||||
WriteInt32(TouchEntryOffset + 0xc, Index++);
|
||||
WriteInt32(TouchEntryOffset + 0x10, Point.X);
|
||||
WriteInt32(TouchEntryOffset + 0x14, Point.Y);
|
||||
WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX);
|
||||
WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY);
|
||||
WriteInt32(TouchEntryOffset + 0x20, Point.Angle);
|
||||
WriteInt32(TouchEntryOffset + 0x24, Padding);
|
||||
|
||||
TouchEntryOffset += HidTouchEntryTouchSize;
|
||||
}
|
||||
}
|
||||
TouchEntryOffset += HidTouchEntryTouchSize;
|
||||
}
|
||||
}
|
||||
|
||||
private unsafe long ReadInt64(long Position)
|
||||
{
|
||||
if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return 0;
|
||||
|
||||
return *((long*)((byte*)Ram + Position));
|
||||
return *((long*)((byte*)Ram + PA + Position));
|
||||
}
|
||||
|
||||
private unsafe void WriteInt32(long Position, int Value)
|
||||
{
|
||||
if ((ulong)Position + 4 > AMemoryMgr.AddrSize) return;
|
||||
|
||||
*((int*)((byte*)Ram + Position)) = Value;
|
||||
*((int*)((byte*)Ram + PA + Position)) = Value;
|
||||
}
|
||||
|
||||
private unsafe void WriteInt64(long Position, long Value)
|
||||
{
|
||||
if ((ulong)Position + 8 > AMemoryMgr.AddrSize) return;
|
||||
|
||||
*((long*)((byte*)Ram + Position)) = Value;
|
||||
*((long*)((byte*)Ram + PA + Position)) = Value;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,13 +28,17 @@ namespace Ryujinx.Core.Loaders
|
|||
this.ImageBase = ImageBase;
|
||||
this.ImageEnd = ImageBase;
|
||||
|
||||
WriteData(ImageBase + Exe.TextOffset, Exe.Text, MemoryType.CodeStatic, AMemoryPerm.RX);
|
||||
WriteData(ImageBase + Exe.ROOffset, Exe.RO, MemoryType.Normal, AMemoryPerm.Read);
|
||||
WriteData(ImageBase + Exe.DataOffset, Exe.Data, MemoryType.Normal, AMemoryPerm.RW);
|
||||
Memory.Manager.MapDirectRX(ImageBase + Exe.TextOffset, Exe.Text.Length, (int)MemoryType.CodeStatic);
|
||||
Memory.Manager.MapDirectRO(ImageBase + Exe.ROOffset, Exe.RO.Length, (int)MemoryType.Normal);
|
||||
Memory.Manager.MapDirectRW(ImageBase + Exe.DataOffset, Exe.Data.Length, (int)MemoryType.Normal);
|
||||
|
||||
Memory.WriteDirectUnchecked(ImageBase + Exe.TextOffset, Exe.Text);
|
||||
Memory.WriteDirectUnchecked(ImageBase + Exe.ROOffset, Exe.RO);
|
||||
Memory.WriteDirectUnchecked(ImageBase + Exe.DataOffset, Exe.Data);
|
||||
|
||||
if (Exe.Mod0Offset == 0)
|
||||
{
|
||||
int BssOffset = Exe.DataOffset + Exe.Data.Count;
|
||||
int BssOffset = Exe.DataOffset + Exe.Data.Length;
|
||||
int BssSize = Exe.BssSize;
|
||||
|
||||
MapBss(ImageBase + BssOffset, BssSize);
|
||||
|
@ -90,25 +94,9 @@ namespace Ryujinx.Core.Loaders
|
|||
}
|
||||
}
|
||||
|
||||
private void WriteData(
|
||||
long Position,
|
||||
IList<byte> Data,
|
||||
MemoryType Type,
|
||||
AMemoryPerm Perm)
|
||||
{
|
||||
Memory.Manager.Map(Position, Data.Count, (int)Type, AMemoryPerm.Write);
|
||||
|
||||
for (int Index = 0; Index < Data.Count; Index++)
|
||||
{
|
||||
Memory.WriteByte(Position + Index, Data[Index]);
|
||||
}
|
||||
|
||||
Memory.Manager.Reprotect(Position, Data.Count, Perm);
|
||||
}
|
||||
|
||||
private void MapBss(long Position, long Size)
|
||||
{
|
||||
Memory.Manager.Map(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
Memory.Manager.MapDirectRW(Position, Size, (int)MemoryType.Normal);
|
||||
}
|
||||
|
||||
private ElfRel GetRelocation(long Position)
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Ryujinx.Core.Loaders.Executables
|
||||
{
|
||||
public interface IExecutable
|
||||
{
|
||||
ReadOnlyCollection<byte> Text { get; }
|
||||
ReadOnlyCollection<byte> RO { get; }
|
||||
ReadOnlyCollection<byte> Data { get; }
|
||||
byte[] Text { get; }
|
||||
byte[] RO { get; }
|
||||
byte[] Data { get; }
|
||||
|
||||
int Mod0Offset { get; }
|
||||
int TextOffset { get; }
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Core.Loaders.Executables
|
||||
{
|
||||
class Nro : IExecutable
|
||||
{
|
||||
private byte[] m_Text;
|
||||
private byte[] m_RO;
|
||||
private byte[] m_Data;
|
||||
|
||||
public ReadOnlyCollection<byte> Text => Array.AsReadOnly(m_Text);
|
||||
public ReadOnlyCollection<byte> RO => Array.AsReadOnly(m_RO);
|
||||
public ReadOnlyCollection<byte> Data => Array.AsReadOnly(m_Data);
|
||||
public byte[] Text { get; private set; }
|
||||
public byte[] RO { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
|
||||
public int Mod0Offset { get; private set; }
|
||||
public int TextOffset { get; private set; }
|
||||
|
@ -54,9 +48,9 @@ namespace Ryujinx.Core.Loaders.Executables
|
|||
return Reader.ReadBytes(Size);
|
||||
}
|
||||
|
||||
m_Text = Read(TextOffset, TextSize);
|
||||
m_RO = Read(ROOffset, ROSize);
|
||||
m_Data = Read(DataOffset, DataSize);
|
||||
Text = Read(TextOffset, TextSize);
|
||||
RO = Read(ROOffset, ROSize);
|
||||
Data = Read(DataOffset, DataSize);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,19 +1,14 @@
|
|||
using Ryujinx.Core.Loaders.Compression;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.Core.Loaders.Executables
|
||||
{
|
||||
class Nso : IExecutable
|
||||
{
|
||||
private byte[] m_Text;
|
||||
private byte[] m_RO;
|
||||
private byte[] m_Data;
|
||||
|
||||
public ReadOnlyCollection<byte> Text => Array.AsReadOnly(m_Text);
|
||||
public ReadOnlyCollection<byte> RO => Array.AsReadOnly(m_RO);
|
||||
public ReadOnlyCollection<byte> Data => Array.AsReadOnly(m_Data);
|
||||
public byte[] Text { get; private set; }
|
||||
public byte[] RO { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
|
||||
public int Mod0Offset { get; private set; }
|
||||
public int TextOffset { get; private set; }
|
||||
|
@ -82,38 +77,38 @@ namespace Ryujinx.Core.Loaders.Executables
|
|||
//Text segment
|
||||
Input.Seek(TextOffset, SeekOrigin.Begin);
|
||||
|
||||
m_Text = Reader.ReadBytes(TextSize);
|
||||
Text = Reader.ReadBytes(TextSize);
|
||||
|
||||
if (Flags.HasFlag(NsoFlags.IsTextCompressed) || true)
|
||||
{
|
||||
m_Text = Lz4.Decompress(m_Text, TextDecSize);
|
||||
Text = Lz4.Decompress(Text, TextDecSize);
|
||||
}
|
||||
|
||||
//Read-only data segment
|
||||
Input.Seek(ROOffset, SeekOrigin.Begin);
|
||||
|
||||
m_RO = Reader.ReadBytes(ROSize);
|
||||
RO = Reader.ReadBytes(ROSize);
|
||||
|
||||
if (Flags.HasFlag(NsoFlags.IsROCompressed) || true)
|
||||
{
|
||||
m_RO = Lz4.Decompress(m_RO, RODecSize);
|
||||
RO = Lz4.Decompress(RO, RODecSize);
|
||||
}
|
||||
|
||||
//Data segment
|
||||
Input.Seek(DataOffset, SeekOrigin.Begin);
|
||||
|
||||
m_Data = Reader.ReadBytes(DataSize);
|
||||
Data = Reader.ReadBytes(DataSize);
|
||||
|
||||
if (Flags.HasFlag(NsoFlags.IsDataCompressed) || true)
|
||||
{
|
||||
m_Data = Lz4.Decompress(m_Data, DataDecSize);
|
||||
Data = Lz4.Decompress(Data, DataDecSize);
|
||||
}
|
||||
|
||||
using (MemoryStream Text = new MemoryStream(m_Text))
|
||||
using (MemoryStream TextSegm = new MemoryStream(Text))
|
||||
{
|
||||
BinaryReader TextReader = new BinaryReader(Text);
|
||||
BinaryReader TextReader = new BinaryReader(TextSegm);
|
||||
|
||||
Text.Seek(4, SeekOrigin.Begin);
|
||||
TextSegm.Seek(4, SeekOrigin.Begin);
|
||||
|
||||
Mod0Offset = TextReader.ReadInt32();
|
||||
}
|
||||
|
|
|
@ -1,43 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Core.OsHle.Handles
|
||||
{
|
||||
class HSharedMem
|
||||
{
|
||||
private List<long> Positions;
|
||||
public long PA { get; private set; }
|
||||
|
||||
public EventHandler<EventArgs> MemoryMapped;
|
||||
public EventHandler<EventArgs> MemoryUnmapped;
|
||||
|
||||
public HSharedMem()
|
||||
public HSharedMem(long PA)
|
||||
{
|
||||
Positions = new List<long>();
|
||||
}
|
||||
|
||||
public void AddVirtualPosition(long Position)
|
||||
{
|
||||
lock (Positions)
|
||||
{
|
||||
Positions.Add(Position);
|
||||
|
||||
MemoryMapped?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveVirtualPosition(long Position)
|
||||
{
|
||||
lock (Positions)
|
||||
{
|
||||
Positions.Remove(Position);
|
||||
|
||||
MemoryUnmapped?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
public long[] GetVirtualPositions()
|
||||
{
|
||||
return Positions.ToArray();
|
||||
this.PA = PA;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Core.OsHle
|
|||
//http://switchbrew.org/index.php?title=Homebrew_ABI
|
||||
public static void WriteHbAbiData(AMemory Memory, long Position, int MainThreadHandle)
|
||||
{
|
||||
Memory.Manager.Map(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
Memory.Manager.MapDirectRW(Position, AMemoryMgr.PageSize, (int)MemoryType.Normal);
|
||||
|
||||
//MainThreadHandle
|
||||
WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle);
|
||||
|
|
|
@ -47,11 +47,11 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
Processes = new ConcurrentDictionary<int, Process>();
|
||||
|
||||
HidSharedMem = new HSharedMem();
|
||||
HidSharedMem = new HSharedMem(Ns.Hid.PA);
|
||||
|
||||
HidHandle = Handles.GenerateId(HidSharedMem);
|
||||
|
||||
FontHandle = Handles.GenerateId(new HSharedMem());
|
||||
FontHandle = Handles.GenerateId(new HSharedMem(0x5000));
|
||||
}
|
||||
|
||||
public void LoadCart(string ExeFsDir, string RomFsFile = null)
|
||||
|
|
|
@ -217,16 +217,26 @@ namespace Ryujinx.Core.OsHle.Ipc
|
|||
|
||||
public long GetSendBuffPtr()
|
||||
{
|
||||
if (SendBuff.Count > 0 && SendBuff[0].Position != 0)
|
||||
if (SendBuff.Count > 0 && SendBuff[0].Size != 0)
|
||||
{
|
||||
return SendBuff[0].Position;
|
||||
}
|
||||
|
||||
if (PtrBuff.Count > 0 && PtrBuff[0].Position != 0)
|
||||
if (PtrBuff.Count > 0 && PtrBuff[0].Size != 0)
|
||||
{
|
||||
return PtrBuff[0].Position;
|
||||
}
|
||||
|
||||
if (ReceiveBuff.Count > 0 && ReceiveBuff[0].Size != 0)
|
||||
{
|
||||
return ReceiveBuff[0].Position;
|
||||
}
|
||||
|
||||
if (RecvListBuff.Count > 0 && RecvListBuff[0].Size != 0)
|
||||
{
|
||||
return RecvListBuff[0].Position;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
using ChocolArm64.Memory;
|
||||
|
||||
namespace Ryujinx.Core.OsHle
|
||||
{
|
||||
static class MemoryRegions
|
||||
{
|
||||
public const long RamSize = 1L << 32;
|
||||
public const long AddrSpaceStart = 0x08000000;
|
||||
public const int AddrSpaceBits = 38;
|
||||
public const long AddrSpaceSize = 1L << AddrSpaceBits;
|
||||
|
||||
public const long MapRegionAddress = 0x10000000;
|
||||
public const long MapRegionSize = 0x20000000;
|
||||
|
||||
public const long MainStackSize = 0x100000;
|
||||
|
||||
public const long MainStackAddress = AMemoryMgr.AddrSize - MainStackSize;
|
||||
public const long MainStackAddress = RamSize - MainStackSize;
|
||||
|
||||
public const long TlsPagesSize = 0x4000;
|
||||
|
||||
|
@ -21,8 +22,8 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
public const long TotalMemoryUsed = HeapRegionAddress + TlsPagesSize + MainStackSize;
|
||||
|
||||
public const long TotalMemoryAvailable = AMemoryMgr.RamSize - AddrSpaceStart;
|
||||
public const long TotalMemoryAvailable = RamSize - AddrSpaceStart;
|
||||
|
||||
public const long AddrSpaceSize = AMemoryMgr.AddrSize - AddrSpaceStart;
|
||||
|
||||
}
|
||||
}
|
|
@ -45,7 +45,7 @@ namespace Ryujinx.Core.OsHle
|
|||
this.Ns = Ns;
|
||||
this.ProcessId = ProcessId;
|
||||
|
||||
Memory = new AMemory(Ns.Ram);
|
||||
Memory = new AMemory(Ns.Ram, MemoryRegions.RamSize, MemoryRegions.AddrSpaceBits);
|
||||
|
||||
Scheduler = new KProcessScheduler();
|
||||
|
||||
|
@ -59,10 +59,10 @@ namespace Ryujinx.Core.OsHle
|
|||
|
||||
ImageBase = MemoryRegions.AddrSpaceStart;
|
||||
|
||||
MapRWMemRegion(
|
||||
Memory.Manager.MapDirectRW(
|
||||
MemoryRegions.TlsPagesAddress,
|
||||
MemoryRegions.TlsPagesSize,
|
||||
MemoryType.ThreadLocal);
|
||||
(int)MemoryType.ThreadLocal);
|
||||
}
|
||||
|
||||
public void LoadProgram(IExecutable Program)
|
||||
|
@ -88,10 +88,10 @@ namespace Ryujinx.Core.OsHle
|
|||
return false;
|
||||
}
|
||||
|
||||
MapRWMemRegion(
|
||||
Memory.Manager.MapDirectRW(
|
||||
MemoryRegions.MainStackAddress,
|
||||
MemoryRegions.MainStackSize,
|
||||
MemoryType.Normal);
|
||||
(int)MemoryType.Normal);
|
||||
|
||||
long StackTop = MemoryRegions.MainStackAddress + MemoryRegions.MainStackSize;
|
||||
|
||||
|
@ -119,11 +119,6 @@ namespace Ryujinx.Core.OsHle
|
|||
return true;
|
||||
}
|
||||
|
||||
private void MapRWMemRegion(long Position, long Size, MemoryType Type)
|
||||
{
|
||||
Memory.Manager.Map(Position, Size, (int)Type, AMemoryPerm.RW);
|
||||
}
|
||||
|
||||
public void StopAllThreads()
|
||||
{
|
||||
if (MainThread != null)
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
FileDesc FdData = Context.Ns.Os.Fds.GetData<FileDesc>(Fd);
|
||||
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
Context.ResponseData.Write(0);
|
||||
|
||||
|
@ -139,7 +139,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuAsIoctlBindChannel(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
int Fd = Context.Memory.ReadInt32(Position);
|
||||
|
||||
|
@ -148,7 +148,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
|
||||
|
@ -174,7 +174,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
|
||||
|
@ -207,7 +207,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
MemWriter Writer = new MemWriter(Context.Memory, Position);
|
||||
|
@ -237,7 +237,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
|
||||
|
@ -254,7 +254,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
MemWriter Writer = new MemWriter(Context.Memory, Position + 0x82);
|
||||
|
@ -269,7 +269,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvHostIoctlCtrlEventWait(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
|
||||
|
@ -285,7 +285,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
Context.Memory.WriteInt32(Position, 1);
|
||||
|
||||
|
@ -294,7 +294,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemWriter Writer = new MemWriter(Context.Memory, Position);
|
||||
|
||||
|
@ -314,7 +314,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
MemWriter Writer = new MemWriter(Context.Memory, Position);
|
||||
|
@ -376,7 +376,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
|
||||
|
@ -390,7 +390,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
Context.Memory.WriteInt32(Position + 0, 7);
|
||||
Context.Memory.WriteInt32(Position + 4, 1);
|
||||
|
@ -400,14 +400,14 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvMapIoctlChannelSetUserData(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
int Fd = Context.Memory.ReadInt32(Position);
|
||||
|
||||
|
@ -416,7 +416,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
MemWriter Writer = new MemWriter(Context.Memory, Position + 0x10);
|
||||
|
@ -455,7 +455,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
int ClassNum = Context.Memory.ReadInt32(Position + 0);
|
||||
int Flags = Context.Memory.ReadInt32(Position + 4);
|
||||
|
@ -467,7 +467,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvMapIoctlChannelZcullBind(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
|
||||
|
@ -480,7 +480,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
|
||||
|
@ -494,7 +494,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvMapIoctlChannelSetPriority(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
int Priority = Context.Memory.ReadInt32(Position);
|
||||
|
||||
|
@ -503,7 +503,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices
|
|||
|
||||
private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context)
|
||||
{
|
||||
long Position = Context.Request.PtrBuff[0].Position;
|
||||
long Position = Context.Request.GetSendBuffPtr();
|
||||
|
||||
MemReader Reader = new MemReader(Context.Memory, Position);
|
||||
MemWriter Writer = new MemWriter(Context.Memory, Position + 0xc);
|
||||
|
|
|
@ -268,7 +268,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.Android
|
|||
|
||||
HNvMap NvMap = GetNvMap(Context, Slot);
|
||||
|
||||
if (FbSize < 0 || NvMap.Address < 0 || NvMap.Address + FbSize > AMemoryMgr.AddrSize)
|
||||
if (FbSize < 0 || NvMap.Address < 0 || NvMap.Address + FbSize > MemoryRegions.AddrSpaceSize)
|
||||
{
|
||||
Logging.Error($"Frame buffer address {NvMap.Address:x16} is invalid!");
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
|
||||
if (Size > CurrentHeapSize)
|
||||
{
|
||||
Memory.Manager.Map(Position, Size, (int)MemoryType.Heap, AMemoryPerm.RW);
|
||||
Memory.Manager.MapDirectRW(Position, Size, (int)MemoryType.Heap);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -57,7 +57,9 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
|
||||
AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src);
|
||||
|
||||
Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
|
||||
long PA = Memory.Manager.TranslatePosition(Src);
|
||||
|
||||
Memory.Manager.Map(Dst, PA, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
|
||||
|
||||
Memory.Manager.Reprotect(Src, Size, AMemoryPerm.None);
|
||||
|
||||
|
@ -122,11 +124,9 @@ namespace Ryujinx.Core.OsHle.Svc
|
|||
|
||||
if (SharedMem != null)
|
||||
{
|
||||
AMemoryHelper.FillWithZeros(Memory, Src, (int)Size);
|
||||
long PA = SharedMem.PA;
|
||||
|
||||
SharedMem.AddVirtualPosition(Src);
|
||||
|
||||
Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
|
||||
Memory.Manager.Map(Src, PA, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
|
||||
|
||||
ThreadState.X0 = 0;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Timers;
|
||||
|
||||
namespace Ryujinx.Core
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using ChocolArm64.Memory;
|
||||
using Ryujinx.Core.Input;
|
||||
using Ryujinx.Core.OsHle;
|
||||
using Ryujinx.Core.Settings;
|
||||
|
@ -25,21 +24,18 @@ namespace Ryujinx.Core
|
|||
|
||||
public Switch(IGalRenderer Renderer)
|
||||
{
|
||||
Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize);
|
||||
Ram = Marshal.AllocHGlobal((IntPtr)MemoryRegions.RamSize);
|
||||
|
||||
Gpu = new NsGpu(Renderer);
|
||||
|
||||
VFs = new VirtualFs();
|
||||
|
||||
Hid = new Hid(Ram);
|
||||
Hid = new Hid(Ram, 0);
|
||||
|
||||
Statistics = new PerformanceStatistics();
|
||||
|
||||
Os = new Horizon(this);
|
||||
|
||||
Os.HidSharedMem.MemoryMapped += Hid.ShMemMap;
|
||||
Os.HidSharedMem.MemoryUnmapped += Hid.ShMemUnmap;
|
||||
|
||||
Settings = new SetSys();
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,12 @@ namespace Ryujinx.Tests.Cpu
|
|||
|
||||
EntryPoint = Position;
|
||||
|
||||
Ram = Marshal.AllocHGlobal((IntPtr)AMemoryMgr.RamSize);
|
||||
long RamSize = 32 * 1024 * 1024;
|
||||
|
||||
Ram = Marshal.AllocHGlobal((IntPtr)RamSize);
|
||||
ATranslator Translator = new ATranslator();
|
||||
Memory = new AMemory(Ram);
|
||||
Memory.Manager.Map(Position, Size, 2, AMemoryPerm.Read | AMemoryPerm.Write | AMemoryPerm.Execute);
|
||||
Memory = new AMemory(Ram, RamSize, 32);
|
||||
Memory.Manager.MapDirectRW(Position, Size, 2);
|
||||
Thread = new AThread(Translator, Memory, ThreadPriority.Normal, EntryPoint);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue