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