forked from Mirror/Ryujinx
Allow to enable/disable memory checks even on release mode through the flag, return error for invalid addresses on SvcMap*Memory svcs, do not return error on SvcQueryMemory (instead, return reserved for the end of the address space), other minor tweaks
This commit is contained in:
parent
553f6c2976
commit
3777fb44cf
15 changed files with 516 additions and 263 deletions
|
@ -1,4 +1,4 @@
|
||||||
public static class AOptimizations
|
public static class AOptimizations
|
||||||
{
|
{
|
||||||
public static bool EnableMemoryChecks = false;
|
public static bool DisableMemoryChecks = false;
|
||||||
}
|
}
|
|
@ -45,21 +45,46 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
switch (Size)
|
switch (Size)
|
||||||
{
|
{
|
||||||
case 0: Name = nameof(AMemory.ReadVector8); break;
|
case 0: Name = AOptimizations.DisableMemoryChecks
|
||||||
case 1: Name = nameof(AMemory.ReadVector16); break;
|
? nameof(AMemory.ReadVector8Unchecked)
|
||||||
case 2: Name = nameof(AMemory.ReadVector32); break;
|
: nameof(AMemory.ReadVector8); break;
|
||||||
case 3: Name = nameof(AMemory.ReadVector64); break;
|
|
||||||
case 4: Name = nameof(AMemory.ReadVector128); break;
|
case 1: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.ReadVector16Unchecked)
|
||||||
|
: nameof(AMemory.ReadVector16); break;
|
||||||
|
|
||||||
|
case 2: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.ReadVector32Unchecked)
|
||||||
|
: nameof(AMemory.ReadVector32); break;
|
||||||
|
|
||||||
|
case 3: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.ReadVector64Unchecked)
|
||||||
|
: nameof(AMemory.ReadVector64); break;
|
||||||
|
|
||||||
|
case 4: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.ReadVector128Unchecked)
|
||||||
|
: nameof(AMemory.ReadVector128); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (Size)
|
switch (Size)
|
||||||
{
|
{
|
||||||
case 0: Name = nameof(AMemory.ReadByte); break;
|
case 0: Name = AOptimizations.DisableMemoryChecks
|
||||||
case 1: Name = nameof(AMemory.ReadUInt16); break;
|
? nameof(AMemory.ReadByteUnchecked)
|
||||||
case 2: Name = nameof(AMemory.ReadUInt32); break;
|
: nameof(AMemory.ReadByte); break;
|
||||||
case 3: Name = nameof(AMemory.ReadUInt64); break;
|
|
||||||
|
case 1: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.ReadUInt16Unchecked)
|
||||||
|
: nameof(AMemory.ReadUInt16); break;
|
||||||
|
|
||||||
|
case 2: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.ReadUInt32Unchecked)
|
||||||
|
: nameof(AMemory.ReadUInt32); break;
|
||||||
|
|
||||||
|
case 3: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.ReadUInt64Unchecked)
|
||||||
|
: nameof(AMemory.ReadUInt64); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,21 +132,46 @@ namespace ChocolArm64.Instruction
|
||||||
{
|
{
|
||||||
switch (Size)
|
switch (Size)
|
||||||
{
|
{
|
||||||
case 0: Name = nameof(AMemory.WriteVector8); break;
|
case 0: Name = AOptimizations.DisableMemoryChecks
|
||||||
case 1: Name = nameof(AMemory.WriteVector16); break;
|
? nameof(AMemory.WriteVector8Unchecked)
|
||||||
case 2: Name = nameof(AMemory.WriteVector32); break;
|
: nameof(AMemory.WriteVector8); break;
|
||||||
case 3: Name = nameof(AMemory.WriteVector64); break;
|
|
||||||
case 4: Name = nameof(AMemory.WriteVector128); break;
|
case 1: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.WriteVector16Unchecked)
|
||||||
|
: nameof(AMemory.WriteVector16); break;
|
||||||
|
|
||||||
|
case 2: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.WriteVector32Unchecked)
|
||||||
|
: nameof(AMemory.WriteVector32); break;
|
||||||
|
|
||||||
|
case 3: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.WriteVector64Unchecked)
|
||||||
|
: nameof(AMemory.WriteVector64); break;
|
||||||
|
|
||||||
|
case 4: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.WriteVector128Unchecked)
|
||||||
|
: nameof(AMemory.WriteVector128); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (Size)
|
switch (Size)
|
||||||
{
|
{
|
||||||
case 0: Name = nameof(AMemory.WriteByte); break;
|
case 0: Name = AOptimizations.DisableMemoryChecks
|
||||||
case 1: Name = nameof(AMemory.WriteUInt16); break;
|
? nameof(AMemory.WriteByteUnchecked)
|
||||||
case 2: Name = nameof(AMemory.WriteUInt32); break;
|
: nameof(AMemory.WriteByte); break;
|
||||||
case 3: Name = nameof(AMemory.WriteUInt64); break;
|
|
||||||
|
case 1: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.WriteUInt16Unchecked)
|
||||||
|
: nameof(AMemory.WriteUInt16); break;
|
||||||
|
|
||||||
|
case 2: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.WriteUInt32Unchecked)
|
||||||
|
: nameof(AMemory.WriteUInt32); break;
|
||||||
|
|
||||||
|
case 3: Name = AOptimizations.DisableMemoryChecks
|
||||||
|
? nameof(AMemory.WriteUInt64Unchecked)
|
||||||
|
: nameof(AMemory.WriteUInt64); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ using ChocolArm64.Exceptions;
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ChocolArm64.Memory
|
namespace ChocolArm64.Memory
|
||||||
|
@ -139,71 +138,77 @@ namespace ChocolArm64.Memory
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sbyte ReadSByte(long Position) => (sbyte)ReadByte (Position);
|
public sbyte ReadSByte(long Position)
|
||||||
public short ReadInt16(long Position) => (short)ReadUInt16(Position);
|
{
|
||||||
public int ReadInt32(long Position) => (int)ReadUInt32(Position);
|
return (sbyte)ReadByte(Position);
|
||||||
public long ReadInt64(long Position) => (long)ReadUInt64(Position);
|
}
|
||||||
|
|
||||||
|
public short ReadInt16(long Position)
|
||||||
|
{
|
||||||
|
return (short)ReadUInt16(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadInt32(long Position)
|
||||||
|
{
|
||||||
|
return (int)ReadUInt32(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long ReadInt64(long Position)
|
||||||
|
{
|
||||||
|
return (long)ReadUInt64(Position);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public byte ReadByte(long Position)
|
public byte ReadByte(long Position)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
EnsureAccessIsValid(Position, AMemoryPerm.Read);
|
||||||
|
|
||||||
return *((byte*)(RamPtr + (uint)Position));
|
return ReadByteUnchecked(Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ushort ReadUInt16(long Position)
|
public ushort ReadUInt16(long Position)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
|
EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
|
||||||
EnsureAccessIsValid(Position + 1, AMemoryPerm.Read);
|
EnsureAccessIsValid(Position + 1, AMemoryPerm.Read);
|
||||||
|
|
||||||
return *((ushort*)(RamPtr + (uint)Position));
|
return ReadUInt16Unchecked(Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public uint ReadUInt32(long Position)
|
public uint ReadUInt32(long Position)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
|
EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
|
||||||
EnsureAccessIsValid(Position + 3, AMemoryPerm.Read);
|
EnsureAccessIsValid(Position + 3, AMemoryPerm.Read);
|
||||||
|
|
||||||
return *((uint*)(RamPtr + (uint)Position));
|
return ReadUInt32Unchecked(Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public ulong ReadUInt64(long Position)
|
public ulong ReadUInt64(long Position)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
|
EnsureAccessIsValid(Position + 0, AMemoryPerm.Read);
|
||||||
EnsureAccessIsValid(Position + 7, AMemoryPerm.Read);
|
EnsureAccessIsValid(Position + 7, AMemoryPerm.Read);
|
||||||
|
|
||||||
return *((ulong*)(RamPtr + (uint)Position));
|
return ReadUInt64Unchecked(Position);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public AVec ReadVector8(long Position)
|
public AVec ReadVector8(long Position)
|
||||||
{
|
{
|
||||||
return new AVec() { B0 = ReadByte(Position) };
|
return new AVec() { B0 = ReadByte(Position) };
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public AVec ReadVector16(long Position)
|
public AVec ReadVector16(long Position)
|
||||||
{
|
{
|
||||||
return new AVec() { H0 = ReadUInt16(Position) };
|
return new AVec() { H0 = ReadUInt16(Position) };
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public AVec ReadVector32(long Position)
|
public AVec ReadVector32(long Position)
|
||||||
{
|
{
|
||||||
return new AVec() { W0 = ReadUInt32(Position) };
|
return new AVec() { W0 = ReadUInt32(Position) };
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public AVec ReadVector64(long Position)
|
public AVec ReadVector64(long Position)
|
||||||
{
|
{
|
||||||
return new AVec() { X0 = ReadUInt64(Position) };
|
return new AVec() { X0 = ReadUInt64(Position) };
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public AVec ReadVector128(long Position)
|
public AVec ReadVector128(long Position)
|
||||||
{
|
{
|
||||||
return new AVec()
|
return new AVec()
|
||||||
|
@ -213,81 +218,219 @@ namespace ChocolArm64.Memory
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteSByte(long Position, sbyte Value) => WriteByte (Position, (byte)Value);
|
public sbyte ReadSByteUnchecked(long Position)
|
||||||
public void WriteInt16(long Position, short Value) => WriteUInt16(Position, (ushort)Value);
|
{
|
||||||
public void WriteInt32(long Position, int Value) => WriteUInt32(Position, (uint)Value);
|
return (sbyte)ReadByteUnchecked(Position);
|
||||||
public void WriteInt64(long Position, long Value) => WriteUInt64(Position, (ulong)Value);
|
}
|
||||||
|
|
||||||
|
public short ReadInt16Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return (short)ReadUInt16Unchecked(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ReadInt32Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return (int)ReadUInt32Unchecked(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long ReadInt64Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return (long)ReadUInt64Unchecked(Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte ReadByteUnchecked(long Position)
|
||||||
|
{
|
||||||
|
return *((byte*)(RamPtr + (uint)Position));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ushort ReadUInt16Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return *((ushort*)(RamPtr + (uint)Position));
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint ReadUInt32Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return *((uint*)(RamPtr + (uint)Position));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ulong ReadUInt64Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return *((ulong*)(RamPtr + (uint)Position));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AVec ReadVector8Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return new AVec() { B0 = ReadByteUnchecked(Position) };
|
||||||
|
}
|
||||||
|
|
||||||
|
public AVec ReadVector16Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return new AVec() { H0 = ReadUInt16Unchecked(Position) };
|
||||||
|
}
|
||||||
|
|
||||||
|
public AVec ReadVector32Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return new AVec() { W0 = ReadUInt32Unchecked(Position) };
|
||||||
|
}
|
||||||
|
|
||||||
|
public AVec ReadVector64Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return new AVec() { X0 = ReadUInt64Unchecked(Position) };
|
||||||
|
}
|
||||||
|
|
||||||
|
public AVec ReadVector128Unchecked(long Position)
|
||||||
|
{
|
||||||
|
return new AVec()
|
||||||
|
{
|
||||||
|
X0 = ReadUInt64Unchecked(Position + 0),
|
||||||
|
X1 = ReadUInt64Unchecked(Position + 8)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteSByte(long Position, sbyte Value)
|
||||||
|
{
|
||||||
|
WriteByte(Position, (byte)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteInt16(long Position, short Value)
|
||||||
|
{
|
||||||
|
WriteUInt16(Position, (ushort)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteInt32(long Position, int Value)
|
||||||
|
{
|
||||||
|
WriteUInt32(Position, (uint)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteInt64(long Position, long Value)
|
||||||
|
{
|
||||||
|
WriteUInt64(Position, (ulong)Value);
|
||||||
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteByte(long Position, byte Value)
|
public void WriteByte(long Position, byte Value)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
EnsureAccessIsValid(Position, AMemoryPerm.Write);
|
||||||
|
|
||||||
*((byte*)(RamPtr + (uint)Position)) = Value;
|
WriteByteUnchecked(Position, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteUInt16(long Position, ushort Value)
|
public void WriteUInt16(long Position, ushort Value)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
|
EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
|
||||||
EnsureAccessIsValid(Position + 1, AMemoryPerm.Write);
|
EnsureAccessIsValid(Position + 1, AMemoryPerm.Write);
|
||||||
|
|
||||||
*((ushort*)(RamPtr + (uint)Position)) = Value;
|
WriteUInt16Unchecked(Position, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteUInt32(long Position, uint Value)
|
public void WriteUInt32(long Position, uint Value)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
|
EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
|
||||||
EnsureAccessIsValid(Position + 3, AMemoryPerm.Write);
|
EnsureAccessIsValid(Position + 3, AMemoryPerm.Write);
|
||||||
|
|
||||||
*((uint*)(RamPtr + (uint)Position)) = Value;
|
WriteUInt32Unchecked(Position, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteUInt64(long Position, ulong Value)
|
public void WriteUInt64(long Position, ulong Value)
|
||||||
{
|
{
|
||||||
EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
|
EnsureAccessIsValid(Position + 0, AMemoryPerm.Write);
|
||||||
EnsureAccessIsValid(Position + 7, AMemoryPerm.Write);
|
EnsureAccessIsValid(Position + 7, AMemoryPerm.Write);
|
||||||
|
|
||||||
*((ulong*)(RamPtr + (uint)Position)) = Value;
|
WriteUInt64Unchecked(Position, Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteVector8(long Position, AVec Value)
|
public void WriteVector8(long Position, AVec Value)
|
||||||
{
|
{
|
||||||
WriteByte(Position, Value.B0);
|
WriteByte(Position, Value.B0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteVector16(long Position, AVec Value)
|
public void WriteVector16(long Position, AVec Value)
|
||||||
{
|
{
|
||||||
WriteUInt16(Position, Value.H0);
|
WriteUInt16(Position, Value.H0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteVector32(long Position, AVec Value)
|
public void WriteVector32(long Position, AVec Value)
|
||||||
{
|
{
|
||||||
WriteUInt32(Position, Value.W0);
|
WriteUInt32(Position, Value.W0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteVector64(long Position, AVec Value)
|
public void WriteVector64(long Position, AVec Value)
|
||||||
{
|
{
|
||||||
WriteUInt64(Position, Value.X0);
|
WriteUInt64(Position, Value.X0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
||||||
public void WriteVector128(long Position, AVec Value)
|
public void WriteVector128(long Position, AVec Value)
|
||||||
{
|
{
|
||||||
WriteUInt64(Position + 0, Value.X0);
|
WriteUInt64(Position + 0, Value.X0);
|
||||||
WriteUInt64(Position + 8, Value.X1);
|
WriteUInt64(Position + 8, Value.X1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EnsureAccessIsValid(long Position, AMemoryPerm Perm)
|
public void WriteSByteUnchecked(long Position, sbyte Value)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
WriteByteUnchecked(Position, (byte)Value);
|
||||||
if (AOptimizations.EnableMemoryChecks)
|
}
|
||||||
|
|
||||||
|
public void WriteInt16Unchecked(long Position, short Value)
|
||||||
|
{
|
||||||
|
WriteUInt16Unchecked(Position, (ushort)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteInt32Unchecked(long Position, int Value)
|
||||||
|
{
|
||||||
|
WriteUInt32Unchecked(Position, (uint)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteInt64Unchecked(long Position, long Value)
|
||||||
|
{
|
||||||
|
WriteUInt64Unchecked(Position, (ulong)Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteByteUnchecked(long Position, byte Value)
|
||||||
|
{
|
||||||
|
*((byte*)(RamPtr + (uint)Position)) = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteUInt16Unchecked(long Position, ushort Value)
|
||||||
|
{
|
||||||
|
*((ushort*)(RamPtr + (uint)Position)) = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteUInt32Unchecked(long Position, uint Value)
|
||||||
|
{
|
||||||
|
*((uint*)(RamPtr + (uint)Position)) = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteUInt64Unchecked(long Position, ulong Value)
|
||||||
|
{
|
||||||
|
*((ulong*)(RamPtr + (uint)Position)) = Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteVector8Unchecked(long Position, AVec Value)
|
||||||
|
{
|
||||||
|
WriteByteUnchecked(Position, Value.B0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteVector16Unchecked(long Position, AVec Value)
|
||||||
|
{
|
||||||
|
WriteUInt16Unchecked(Position, Value.H0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteVector32Unchecked(long Position, AVec Value)
|
||||||
|
{
|
||||||
|
WriteUInt32Unchecked(Position, Value.W0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteVector64Unchecked(long Position, AVec Value)
|
||||||
|
{
|
||||||
|
WriteUInt64Unchecked(Position, Value.X0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteVector128Unchecked(long Position, AVec Value)
|
||||||
|
{
|
||||||
|
WriteUInt64Unchecked(Position + 0, Value.X0);
|
||||||
|
WriteUInt64Unchecked(Position + 8, Value.X1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureAccessIsValid(long Position, AMemoryPerm Perm)
|
||||||
{
|
{
|
||||||
if (!Manager.IsMapped(Position))
|
if (!Manager.IsMapped(Position))
|
||||||
{
|
{
|
||||||
|
@ -299,8 +442,6 @@ namespace ChocolArm64.Memory
|
||||||
throw new VmmAccessViolationException(Position, Perm);
|
throw new VmmAccessViolationException(Position, Perm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Ryujinx.Core.OsHle.Handles;
|
using ChocolArm64.Memory;
|
||||||
|
using Ryujinx.Core.OsHle.Handles;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.Core.Input
|
namespace Ryujinx.Core.Input
|
||||||
|
@ -64,15 +65,11 @@ namespace Ryujinx.Core.Input
|
||||||
|
|
||||||
private long[] ShMemPositions;
|
private long[] ShMemPositions;
|
||||||
|
|
||||||
private long CurrControllerEntry;
|
private AMemory Memory;
|
||||||
private long CurrTouchEntry;
|
|
||||||
private long CurrTouchSampleCounter;
|
|
||||||
|
|
||||||
private Switch Ns;
|
public Hid(AMemory Memory)
|
||||||
|
|
||||||
public Hid(Switch Ns)
|
|
||||||
{
|
{
|
||||||
this.Ns = Ns;
|
this.Memory = Memory;
|
||||||
|
|
||||||
ShMemLock = new object();
|
ShMemLock = new object();
|
||||||
|
|
||||||
|
@ -138,20 +135,20 @@ namespace Ryujinx.Core.Input
|
||||||
|
|
||||||
HidControllerColorDesc SplitColorDesc = 0;
|
HidControllerColorDesc SplitColorDesc = 0;
|
||||||
|
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x0, (int)Type);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x0, (int)Type);
|
||||||
|
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x4, IsHalf ? 1 : 0);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x4, IsHalf ? 1 : 0);
|
||||||
|
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x8, (int)SingleColorDesc);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x8, (int)SingleColorDesc);
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0xc, (int)SingleColorBody);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0xc, (int)SingleColorBody);
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x10, (int)SingleColorButtons);
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x14, (int)SplitColorDesc);
|
||||||
|
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x18, (int)LeftColorBody);
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x1c, (int)LeftColorButtons);
|
||||||
|
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x20, (int)RightColorBody);
|
||||||
Ns.Memory.WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons);
|
Memory.WriteInt32Unchecked(BaseControllerOffset + 0x24, (int)RightColorButtons);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetJoyconButton(
|
public void SetJoyconButton(
|
||||||
|
@ -165,26 +162,7 @@ namespace Ryujinx.Core.Input
|
||||||
{
|
{
|
||||||
foreach (long Position in ShMemPositions)
|
foreach (long Position in ShMemPositions)
|
||||||
{
|
{
|
||||||
WriteJoyconButtons(
|
long ControllerOffset = Position + HidControllersOffset;
|
||||||
Position,
|
|
||||||
ControllerId,
|
|
||||||
ControllerLayout,
|
|
||||||
Buttons,
|
|
||||||
LeftStick,
|
|
||||||
RightStick);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteJoyconButtons(
|
|
||||||
long BasePosition,
|
|
||||||
HidControllerId ControllerId,
|
|
||||||
HidControllerLayouts ControllerLayout,
|
|
||||||
HidControllerButtons Buttons,
|
|
||||||
HidJoystickPosition LeftStick,
|
|
||||||
HidJoystickPosition RightStick)
|
|
||||||
{
|
|
||||||
long ControllerOffset = BasePosition + HidControllersOffset;
|
|
||||||
|
|
||||||
ControllerOffset += (int)ControllerId * HidControllerSize;
|
ControllerOffset += (int)ControllerId * HidControllerSize;
|
||||||
|
|
||||||
|
@ -192,34 +170,38 @@ namespace Ryujinx.Core.Input
|
||||||
|
|
||||||
ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
|
ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize;
|
||||||
|
|
||||||
CurrControllerEntry = (CurrControllerEntry + 1) % HidEntryCount;
|
long LastEntry = Memory.ReadInt64Unchecked(ControllerOffset + 0x10);
|
||||||
|
|
||||||
|
long CurrEntry = (LastEntry + 1) % HidEntryCount;
|
||||||
|
|
||||||
long Timestamp = GetTimestamp();
|
long Timestamp = GetTimestamp();
|
||||||
|
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x0, Timestamp);
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x8, HidEntryCount);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x8, HidEntryCount);
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x10, CurrControllerEntry);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x10, CurrEntry);
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x18, HidEntryCount - 1);
|
||||||
|
|
||||||
ControllerOffset += HidControllersLayoutHeaderSize;
|
ControllerOffset += HidControllersLayoutHeaderSize;
|
||||||
|
|
||||||
ControllerOffset += CurrControllerEntry * HidControllersInputEntrySize;
|
ControllerOffset += CurrEntry * HidControllersInputEntrySize;
|
||||||
|
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x0, Timestamp);
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x8, Timestamp);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x8, Timestamp);
|
||||||
|
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x10, (uint)Buttons);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x10, (uint)Buttons);
|
||||||
|
|
||||||
Ns.Memory.WriteInt32(ControllerOffset + 0x18, LeftStick.DX);
|
Memory.WriteInt32Unchecked(ControllerOffset + 0x18, LeftStick.DX);
|
||||||
Ns.Memory.WriteInt32(ControllerOffset + 0x1c, LeftStick.DY);
|
Memory.WriteInt32Unchecked(ControllerOffset + 0x1c, LeftStick.DY);
|
||||||
|
|
||||||
Ns.Memory.WriteInt32(ControllerOffset + 0x20, RightStick.DX);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x20, RightStick.DX);
|
||||||
Ns.Memory.WriteInt32(ControllerOffset + 0x24, RightStick.DY);
|
Memory.WriteInt64Unchecked(ControllerOffset + 0x24, RightStick.DY);
|
||||||
|
|
||||||
Ns.Memory.WriteInt64(ControllerOffset + 0x28,
|
Memory.WriteInt64Unchecked(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)
|
||||||
{
|
{
|
||||||
|
@ -227,31 +209,30 @@ namespace Ryujinx.Core.Input
|
||||||
{
|
{
|
||||||
foreach (long Position in ShMemPositions)
|
foreach (long Position in ShMemPositions)
|
||||||
{
|
{
|
||||||
WriteTouchPoints(Position, Points);
|
long TouchScreenOffset = Position + HidTouchScreenOffset;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void WriteTouchPoints(long BasePosition, params HidTouchPoint[] Points)
|
long LastEntry = Memory.ReadInt64Unchecked(TouchScreenOffset + 0x10);
|
||||||
{
|
|
||||||
long TouchScreenOffset = BasePosition + HidTouchScreenOffset;
|
long CurrEntry = (LastEntry + 1) % HidEntryCount;
|
||||||
|
|
||||||
long Timestamp = GetTimestamp();
|
long Timestamp = GetTimestamp();
|
||||||
|
|
||||||
CurrTouchEntry = (CurrTouchEntry + 1) % HidEntryCount;
|
Memory.WriteInt64Unchecked(TouchScreenOffset + 0x0, Timestamp);
|
||||||
|
Memory.WriteInt64Unchecked(TouchScreenOffset + 0x8, HidEntryCount);
|
||||||
Ns.Memory.WriteInt64(TouchScreenOffset + 0x0, Timestamp);
|
Memory.WriteInt64Unchecked(TouchScreenOffset + 0x10, CurrEntry);
|
||||||
Ns.Memory.WriteInt64(TouchScreenOffset + 0x8, HidEntryCount);
|
Memory.WriteInt64Unchecked(TouchScreenOffset + 0x18, HidEntryCount - 1);
|
||||||
Ns.Memory.WriteInt64(TouchScreenOffset + 0x10, CurrTouchEntry);
|
Memory.WriteInt64Unchecked(TouchScreenOffset + 0x20, Timestamp);
|
||||||
Ns.Memory.WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1);
|
|
||||||
Ns.Memory.WriteInt64(TouchScreenOffset + 0x20, Timestamp);
|
|
||||||
|
|
||||||
long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
|
long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize;
|
||||||
|
|
||||||
TouchEntryOffset += CurrTouchEntry * HidTouchEntrySize;
|
long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize;
|
||||||
|
|
||||||
Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, CurrTouchSampleCounter++);
|
long SampleCounter = Memory.ReadInt64Unchecked(LastEntryOffset) + 1;
|
||||||
Ns.Memory.WriteInt64(TouchEntryOffset + 0x8, Points.Length);
|
|
||||||
|
TouchEntryOffset += CurrEntry * HidTouchEntrySize;
|
||||||
|
|
||||||
|
Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0, SampleCounter);
|
||||||
|
Memory.WriteInt64Unchecked(TouchEntryOffset + 0x8, Points.Length);
|
||||||
|
|
||||||
TouchEntryOffset += HidTouchEntryHeaderSize;
|
TouchEntryOffset += HidTouchEntryHeaderSize;
|
||||||
|
|
||||||
|
@ -261,19 +242,21 @@ namespace Ryujinx.Core.Input
|
||||||
|
|
||||||
foreach (HidTouchPoint Point in Points)
|
foreach (HidTouchPoint Point in Points)
|
||||||
{
|
{
|
||||||
Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, Timestamp);
|
Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0, Timestamp);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0x8, Padding);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0x8, Padding);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0xc, Index++);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0xc, Index++);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0x10, Point.X);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0x10, Point.X);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0x14, Point.Y);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0x14, Point.Y);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0x18, Point.DiameterX);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0x1c, Point.DiameterY);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0x20, Point.Angle);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0x20, Point.Angle);
|
||||||
Ns.Memory.WriteInt32(TouchEntryOffset + 0x24, Padding);
|
Memory.WriteInt32Unchecked(TouchEntryOffset + 0x24, Padding);
|
||||||
|
|
||||||
TouchEntryOffset += HidTouchEntryTouchSize;
|
TouchEntryOffset += HidTouchEntryTouchSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private long GetTimestamp()
|
private long GetTimestamp()
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace Ryujinx.Core.Loaders
|
||||||
|
|
||||||
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);
|
||||||
|
@ -92,18 +92,15 @@ namespace Ryujinx.Core.Loaders
|
||||||
|
|
||||||
private void WriteData(
|
private void WriteData(
|
||||||
long Position,
|
long Position,
|
||||||
IList<byte> Data,
|
byte[] Data,
|
||||||
MemoryType Type,
|
MemoryType Type,
|
||||||
AMemoryPerm Perm)
|
AMemoryPerm Perm)
|
||||||
{
|
{
|
||||||
Memory.Manager.Map(Position, Data.Count, (int)Type, AMemoryPerm.Write);
|
Memory.Manager.Map(Position, Data.Length, (int)Type, AMemoryPerm.Write);
|
||||||
|
|
||||||
for (int Index = 0; Index < Data.Count; Index++)
|
AMemoryHelper.WriteBytes(Memory, Position, Data);
|
||||||
{
|
|
||||||
Memory.WriteByte(Position + Index, Data[Index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
Memory.Manager.Reprotect(Position, Data.Count, Perm);
|
Memory.Manager.Reprotect(Position, Data.Length, Perm);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapBss(long Position, long Size)
|
private void MapBss(long Position, long Size)
|
||||||
|
|
|
@ -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 TextMS = new MemoryStream(Text))
|
||||||
{
|
{
|
||||||
BinaryReader TextReader = new BinaryReader(Text);
|
BinaryReader TextReader = new BinaryReader(TextMS);
|
||||||
|
|
||||||
Text.Seek(4, SeekOrigin.Begin);
|
TextMS.Seek(4, SeekOrigin.Begin);
|
||||||
|
|
||||||
Mod0Offset = TextReader.ReadInt32();
|
Mod0Offset = TextReader.ReadInt32();
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,8 @@ namespace Ryujinx.Core.OsHle
|
||||||
HidHandle = Handles.GenerateId(HidSharedMem);
|
HidHandle = Handles.GenerateId(HidSharedMem);
|
||||||
|
|
||||||
FontHandle = Handles.GenerateId(new HSharedMem());
|
FontHandle = Handles.GenerateId(new HSharedMem());
|
||||||
|
|
||||||
|
HidSharedMem.AddVirtualPosition(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -55,6 +55,24 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
long Src = (long)ThreadState.X1;
|
long Src = (long)ThreadState.X1;
|
||||||
long Size = (long)ThreadState.X2;
|
long Size = (long)ThreadState.X2;
|
||||||
|
|
||||||
|
if (!IsValidPosition(Src))
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to map Memory at invalid src address {Src:x16}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsValidMapPosition(Dst))
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to map Memory at invalid dst address {Dst:x16}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src);
|
AMemoryMapInfo SrcInfo = Memory.Manager.GetMapInfo(Src);
|
||||||
|
|
||||||
Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
|
Memory.Manager.Map(Dst, Size, (int)MemoryType.MappedMemory, SrcInfo.Perm);
|
||||||
|
@ -72,6 +90,24 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
long Src = (long)ThreadState.X1;
|
long Src = (long)ThreadState.X1;
|
||||||
long Size = (long)ThreadState.X2;
|
long Size = (long)ThreadState.X2;
|
||||||
|
|
||||||
|
if (!IsValidPosition(Src))
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to unmap Memory at invalid src address {Src:x16}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IsValidMapPosition(Dst))
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to unmap Memory at invalid dst address {Dst:x16}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst);
|
AMemoryMapInfo DstInfo = Memory.Manager.GetMapInfo(Dst);
|
||||||
|
|
||||||
Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory);
|
Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory);
|
||||||
|
@ -92,9 +128,11 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
if (MapInfo == null)
|
if (MapInfo == null)
|
||||||
{
|
{
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
long AddrSpaceEnd = MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize;
|
||||||
|
|
||||||
return;
|
long ReservedSize = (long)(ulong.MaxValue - (ulong)AddrSpaceEnd) + 1;
|
||||||
|
|
||||||
|
MapInfo = new AMemoryMapInfo(AddrSpaceEnd, ReservedSize, (int)MemoryType.Reserved, 0, AMemoryPerm.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position);
|
Memory.WriteInt64(InfoPtr + 0x00, MapInfo.Position);
|
||||||
|
@ -118,15 +156,26 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
long Size = (long)ThreadState.X2;
|
long Size = (long)ThreadState.X2;
|
||||||
int Perm = (int)ThreadState.X3;
|
int Perm = (int)ThreadState.X3;
|
||||||
|
|
||||||
|
if (!IsValidPosition(Src))
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to map SharedMemory at invalid address {Src:x16}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HSharedMem SharedMem = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
HSharedMem SharedMem = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
||||||
|
|
||||||
if (SharedMem != null)
|
if (SharedMem != null)
|
||||||
{
|
{
|
||||||
|
Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, AMemoryPerm.Write);
|
||||||
|
|
||||||
AMemoryHelper.FillWithZeros(Memory, Src, (int)Size);
|
AMemoryHelper.FillWithZeros(Memory, Src, (int)Size);
|
||||||
|
|
||||||
SharedMem.AddVirtualPosition(Src);
|
Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm);
|
||||||
|
|
||||||
Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, (AMemoryPerm)Perm);
|
SharedMem.AddVirtualPosition(Src);
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
@ -137,13 +186,24 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
private void SvcUnmapSharedMemory(AThreadState ThreadState)
|
private void SvcUnmapSharedMemory(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
long Position = (long)ThreadState.X1;
|
long Src = (long)ThreadState.X1;
|
||||||
long Size = (long)ThreadState.X2;
|
long Size = (long)ThreadState.X2;
|
||||||
|
|
||||||
|
if (!IsValidPosition(Src))
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to unmap SharedMemory at invalid address {Src:x16}!");
|
||||||
|
|
||||||
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
HSharedMem HndData = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
HSharedMem HndData = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
||||||
|
|
||||||
if (HndData != null)
|
if (HndData != null)
|
||||||
{
|
{
|
||||||
|
Memory.Manager.Unmap(Src, Size, (int)MemoryType.SharedMemory);
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,20 +212,41 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
private void SvcCreateTransferMemory(AThreadState ThreadState)
|
private void SvcCreateTransferMemory(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
long Position = (long)ThreadState.X1;
|
long Src = (long)ThreadState.X1;
|
||||||
long Size = (long)ThreadState.X2;
|
long Size = (long)ThreadState.X2;
|
||||||
int Perm = (int)ThreadState.X3;
|
int Perm = (int)ThreadState.X3;
|
||||||
|
|
||||||
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
|
if (!IsValidPosition(Src))
|
||||||
|
{
|
||||||
|
Logging.Warn($"Tried to create TransferMemory at invalid address {Src:x16}!");
|
||||||
|
|
||||||
Memory.Manager.Reprotect(Position, Size, (AMemoryPerm)Perm);
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidMemRange);
|
||||||
|
|
||||||
HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Position, Size);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Src);
|
||||||
|
|
||||||
|
Memory.Manager.Reprotect(Src, Size, (AMemoryPerm)Perm);
|
||||||
|
|
||||||
|
HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Src, Size);
|
||||||
|
|
||||||
int Handle = Ns.Os.Handles.GenerateId(HndData);
|
int Handle = Ns.Os.Handles.GenerateId(HndData);
|
||||||
|
|
||||||
ThreadState.X1 = (ulong)Handle;
|
ThreadState.X1 = (ulong)Handle;
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsValidPosition(long Position)
|
||||||
|
{
|
||||||
|
return Position >= MemoryRegions.AddrSpaceStart &&
|
||||||
|
Position < MemoryRegions.AddrSpaceStart + MemoryRegions.AddrSpaceSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsValidMapPosition(long Position)
|
||||||
|
{
|
||||||
|
return Position >= MemoryRegions.MapRegionAddress &&
|
||||||
|
Position < MemoryRegions.MapRegionAddress + MemoryRegions.MapRegionSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -30,7 +30,7 @@ namespace Ryujinx.Core
|
||||||
|
|
||||||
VFs = new VirtualFs();
|
VFs = new VirtualFs();
|
||||||
|
|
||||||
Hid = new Hid(this);
|
Hid = new Hid(Memory);
|
||||||
|
|
||||||
Statistics = new PerformanceStatistics();
|
Statistics = new PerformanceStatistics();
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
|
|
||||||
protected void Opcode(uint Opcode)
|
protected void Opcode(uint Opcode)
|
||||||
{
|
{
|
||||||
Thread.Memory.WriteUInt32(Position, Opcode);
|
Thread.Memory.WriteUInt32Unchecked(Position, Opcode);
|
||||||
Position += 4;
|
Position += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@ namespace Ryujinx
|
||||||
{
|
{
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
AOptimizations.DisableMemoryChecks = true;
|
||||||
|
|
||||||
Config.Read();
|
Config.Read();
|
||||||
|
|
||||||
Console.Title = "Ryujinx Console";
|
Console.Title = "Ryujinx Console";
|
||||||
|
|
Loading…
Reference in a new issue