From 3777fb44cf03d05fdedee00f1a19d30fac73b31b Mon Sep 17 00:00:00 2001 From: gdkchan Date: Sat, 10 Mar 2018 20:39:16 -0300 Subject: [PATCH] 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 --- ChocolArm64/AOptimizations.cs | 2 +- .../Instruction/AInstEmitMemoryHelper.cs | 86 +++++-- ChocolArm64/Memory/AMemory.cs | 235 ++++++++++++++---- Ryujinx.Core/Hid/Hid.cs | 211 ++++++++-------- Ryujinx.Core/Loaders/Executable.cs | 13 +- .../Loaders/Executables/IExecutable.cs | 8 +- Ryujinx.Core/Loaders/Executables/Nro.cs | 18 +- Ryujinx.Core/Loaders/Executables/Nso.cs | 35 ++- Ryujinx.Core/OsHle/Horizon.cs | 2 + Ryujinx.Core/OsHle/Ipc/IpcMessage.cs | 14 +- .../OsHle/Services/Nv/ServiceNvDrv.cs | 42 ++-- Ryujinx.Core/OsHle/Svc/SvcMemory.cs | 107 +++++++- Ryujinx.Core/Switch.cs | 2 +- Ryujinx.Tests/Cpu/CpuTest.cs | 2 +- Ryujinx/Ui/Program.cs | 2 + 15 files changed, 516 insertions(+), 263 deletions(-) diff --git a/ChocolArm64/AOptimizations.cs b/ChocolArm64/AOptimizations.cs index 0cdbd76e28..a3c82dccde 100644 --- a/ChocolArm64/AOptimizations.cs +++ b/ChocolArm64/AOptimizations.cs @@ -1,4 +1,4 @@ public static class AOptimizations { - public static bool EnableMemoryChecks = false; + public static bool DisableMemoryChecks = false; } \ No newline at end of file diff --git a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs index d5a0051b5a..6ffcf2dc95 100644 --- a/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs +++ b/ChocolArm64/Instruction/AInstEmitMemoryHelper.cs @@ -45,21 +45,46 @@ namespace ChocolArm64.Instruction { switch (Size) { - case 0: Name = nameof(AMemory.ReadVector8); break; - case 1: Name = nameof(AMemory.ReadVector16); break; - case 2: Name = nameof(AMemory.ReadVector32); break; - case 3: Name = nameof(AMemory.ReadVector64); break; - case 4: Name = nameof(AMemory.ReadVector128); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadVector8Unchecked) + : nameof(AMemory.ReadVector8); 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 { switch (Size) { - case 0: Name = nameof(AMemory.ReadByte); break; - case 1: Name = nameof(AMemory.ReadUInt16); break; - case 2: Name = nameof(AMemory.ReadUInt32); break; - case 3: Name = nameof(AMemory.ReadUInt64); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.ReadByteUnchecked) + : nameof(AMemory.ReadByte); 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) { - case 0: Name = nameof(AMemory.WriteVector8); break; - case 1: Name = nameof(AMemory.WriteVector16); break; - case 2: Name = nameof(AMemory.WriteVector32); break; - case 3: Name = nameof(AMemory.WriteVector64); break; - case 4: Name = nameof(AMemory.WriteVector128); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteVector8Unchecked) + : nameof(AMemory.WriteVector8); 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 { switch (Size) { - case 0: Name = nameof(AMemory.WriteByte); break; - case 1: Name = nameof(AMemory.WriteUInt16); break; - case 2: Name = nameof(AMemory.WriteUInt32); break; - case 3: Name = nameof(AMemory.WriteUInt64); break; + case 0: Name = AOptimizations.DisableMemoryChecks + ? nameof(AMemory.WriteByteUnchecked) + : nameof(AMemory.WriteByte); 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; } } diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs index 7f2dd7d3f4..d7e11189f6 100644 --- a/ChocolArm64/Memory/AMemory.cs +++ b/ChocolArm64/Memory/AMemory.cs @@ -2,7 +2,6 @@ using ChocolArm64.Exceptions; using ChocolArm64.State; using System; using System.Collections.Generic; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace ChocolArm64.Memory @@ -139,71 +138,77 @@ namespace ChocolArm64.Memory } } - public sbyte ReadSByte(long Position) => (sbyte)ReadByte (Position); - public short ReadInt16(long Position) => (short)ReadUInt16(Position); - public int ReadInt32(long Position) => (int)ReadUInt32(Position); - public long ReadInt64(long Position) => (long)ReadUInt64(Position); + public sbyte ReadSByte(long Position) + { + return (sbyte)ReadByte(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) { EnsureAccessIsValid(Position, AMemoryPerm.Read); - return *((byte*)(RamPtr + (uint)Position)); + return ReadByteUnchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ushort ReadUInt16(long Position) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); EnsureAccessIsValid(Position + 1, AMemoryPerm.Read); - return *((ushort*)(RamPtr + (uint)Position)); + return ReadUInt16Unchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public uint ReadUInt32(long Position) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); EnsureAccessIsValid(Position + 3, AMemoryPerm.Read); - return *((uint*)(RamPtr + (uint)Position)); + return ReadUInt32Unchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public ulong ReadUInt64(long Position) { EnsureAccessIsValid(Position + 0, AMemoryPerm.Read); EnsureAccessIsValid(Position + 7, AMemoryPerm.Read); - return *((ulong*)(RamPtr + (uint)Position)); + return ReadUInt64Unchecked(Position); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector8(long Position) { return new AVec() { B0 = ReadByte(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector16(long Position) { return new AVec() { H0 = ReadUInt16(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector32(long Position) { return new AVec() { W0 = ReadUInt32(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector64(long Position) { return new AVec() { X0 = ReadUInt64(Position) }; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public AVec ReadVector128(long Position) { return new AVec() @@ -213,93 +218,229 @@ namespace ChocolArm64.Memory }; } - 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); + public sbyte ReadSByteUnchecked(long Position) + { + return (sbyte)ReadByteUnchecked(Position); + } + + 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) { EnsureAccessIsValid(Position, AMemoryPerm.Write); - *((byte*)(RamPtr + (uint)Position)) = Value; + WriteByteUnchecked(Position, Value); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteUInt16(long Position, ushort Value) { EnsureAccessIsValid(Position + 0, 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) { EnsureAccessIsValid(Position + 0, 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) { EnsureAccessIsValid(Position + 0, 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) { WriteByte(Position, Value.B0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector16(long Position, AVec Value) { WriteUInt16(Position, Value.H0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector32(long Position, AVec Value) { WriteUInt32(Position, Value.W0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector64(long Position, AVec Value) { WriteUInt64(Position, Value.X0); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] public void WriteVector128(long Position, AVec Value) { WriteUInt64(Position + 0, Value.X0); WriteUInt64(Position + 8, Value.X1); } + public void WriteSByteUnchecked(long Position, sbyte Value) + { + WriteByteUnchecked(Position, (byte)Value); + } + + 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 DEBUG - if (AOptimizations.EnableMemoryChecks) + if (!Manager.IsMapped(Position)) { - if (!Manager.IsMapped(Position)) - { - throw new VmmPageFaultException(Position); - } - - if (!Manager.HasPermission(Position, Perm)) - { - throw new VmmAccessViolationException(Position, Perm); - } + throw new VmmPageFaultException(Position); + } + + if (!Manager.HasPermission(Position, Perm)) + { + throw new VmmAccessViolationException(Position, Perm); } -#endif } public void Dispose() diff --git a/Ryujinx.Core/Hid/Hid.cs b/Ryujinx.Core/Hid/Hid.cs index 169768892e..76ecf5ffdf 100644 --- a/Ryujinx.Core/Hid/Hid.cs +++ b/Ryujinx.Core/Hid/Hid.cs @@ -1,4 +1,5 @@ -using Ryujinx.Core.OsHle.Handles; +using ChocolArm64.Memory; +using Ryujinx.Core.OsHle.Handles; using System; namespace Ryujinx.Core.Input @@ -64,15 +65,11 @@ namespace Ryujinx.Core.Input private long[] ShMemPositions; - private long CurrControllerEntry; - private long CurrTouchEntry; - private long CurrTouchSampleCounter; + private AMemory Memory; - private Switch Ns; - - public Hid(Switch Ns) + public Hid(AMemory Memory) { - this.Ns = Ns; + this.Memory = Memory; ShMemLock = new object(); @@ -138,20 +135,20 @@ namespace Ryujinx.Core.Input 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); - Ns.Memory.WriteInt32(BaseControllerOffset + 0xc, (int)SingleColorBody); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x10, (int)SingleColorButtons); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x14, (int)SplitColorDesc); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x8, (int)SingleColorDesc); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0xc, (int)SingleColorBody); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x10, (int)SingleColorButtons); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x14, (int)SplitColorDesc); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x18, (int)LeftColorBody); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x1c, (int)LeftColorButtons); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x18, (int)LeftColorBody); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x1c, (int)LeftColorButtons); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x20, (int)RightColorBody); - Ns.Memory.WriteInt32(BaseControllerOffset + 0x24, (int)RightColorButtons); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x20, (int)RightColorBody); + Memory.WriteInt32Unchecked(BaseControllerOffset + 0x24, (int)RightColorButtons); } public void SetJoyconButton( @@ -165,116 +162,102 @@ namespace Ryujinx.Core.Input { foreach (long Position in ShMemPositions) { - WriteJoyconButtons( - Position, - ControllerId, - ControllerLayout, - Buttons, - LeftStick, - RightStick); + long ControllerOffset = Position + HidControllersOffset; + + ControllerOffset += (int)ControllerId * HidControllerSize; + + ControllerOffset += HidControllerHeaderSize; + + ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; + + long LastEntry = Memory.ReadInt64Unchecked(ControllerOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = GetTimestamp(); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x0, Timestamp); + Memory.WriteInt64Unchecked(ControllerOffset + 0x8, HidEntryCount); + Memory.WriteInt64Unchecked(ControllerOffset + 0x10, CurrEntry); + Memory.WriteInt64Unchecked(ControllerOffset + 0x18, HidEntryCount - 1); + + ControllerOffset += HidControllersLayoutHeaderSize; + + ControllerOffset += CurrEntry * HidControllersInputEntrySize; + + Memory.WriteInt64Unchecked(ControllerOffset + 0x0, Timestamp); + Memory.WriteInt64Unchecked(ControllerOffset + 0x8, Timestamp); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x10, (uint)Buttons); + + Memory.WriteInt32Unchecked(ControllerOffset + 0x18, LeftStick.DX); + Memory.WriteInt32Unchecked(ControllerOffset + 0x1c, LeftStick.DY); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x20, RightStick.DX); + Memory.WriteInt64Unchecked(ControllerOffset + 0x24, RightStick.DY); + + Memory.WriteInt64Unchecked(ControllerOffset + 0x28, + (uint)HidControllerConnState.Controller_State_Connected | + (uint)HidControllerConnState.Controller_State_Wired); } } } - private void WriteJoyconButtons( - long BasePosition, - HidControllerId ControllerId, - HidControllerLayouts ControllerLayout, - HidControllerButtons Buttons, - HidJoystickPosition LeftStick, - HidJoystickPosition RightStick) - { - long ControllerOffset = BasePosition + HidControllersOffset; - - ControllerOffset += (int)ControllerId * HidControllerSize; - - ControllerOffset += HidControllerHeaderSize; - - ControllerOffset += (int)ControllerLayout * HidControllerLayoutsSize; - - CurrControllerEntry = (CurrControllerEntry + 1) % HidEntryCount; - - long Timestamp = GetTimestamp(); - - Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp); - Ns.Memory.WriteInt64(ControllerOffset + 0x8, HidEntryCount); - Ns.Memory.WriteInt64(ControllerOffset + 0x10, CurrControllerEntry); - Ns.Memory.WriteInt64(ControllerOffset + 0x18, HidEntryCount - 1); - - ControllerOffset += HidControllersLayoutHeaderSize; - - ControllerOffset += CurrControllerEntry * HidControllersInputEntrySize; - - Ns.Memory.WriteInt64(ControllerOffset + 0x0, Timestamp); - Ns.Memory.WriteInt64(ControllerOffset + 0x8, Timestamp); - - Ns.Memory.WriteInt64(ControllerOffset + 0x10, (uint)Buttons); - - Ns.Memory.WriteInt32(ControllerOffset + 0x18, LeftStick.DX); - Ns.Memory.WriteInt32(ControllerOffset + 0x1c, LeftStick.DY); - - Ns.Memory.WriteInt32(ControllerOffset + 0x20, RightStick.DX); - Ns.Memory.WriteInt32(ControllerOffset + 0x24, RightStick.DY); - - Ns.Memory.WriteInt64(ControllerOffset + 0x28, - (uint)HidControllerConnState.Controller_State_Connected | - (uint)HidControllerConnState.Controller_State_Wired); - } - public void SetTouchPoints(params HidTouchPoint[] Points) { lock (ShMemLock) { foreach (long Position in ShMemPositions) { - WriteTouchPoints(Position, Points); + long TouchScreenOffset = Position + HidTouchScreenOffset; + + long LastEntry = Memory.ReadInt64Unchecked(TouchScreenOffset + 0x10); + + long CurrEntry = (LastEntry + 1) % HidEntryCount; + + long Timestamp = GetTimestamp(); + + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x0, Timestamp); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x8, HidEntryCount); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x10, CurrEntry); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x18, HidEntryCount - 1); + Memory.WriteInt64Unchecked(TouchScreenOffset + 0x20, Timestamp); + + long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize; + + long LastEntryOffset = TouchEntryOffset + LastEntry * HidTouchEntrySize; + + long SampleCounter = Memory.ReadInt64Unchecked(LastEntryOffset) + 1; + + TouchEntryOffset += CurrEntry * HidTouchEntrySize; + + Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0, SampleCounter); + Memory.WriteInt64Unchecked(TouchEntryOffset + 0x8, Points.Length); + + TouchEntryOffset += HidTouchEntryHeaderSize; + + const int Padding = 0; + + int Index = 0; + + foreach (HidTouchPoint Point in Points) + { + Memory.WriteInt64Unchecked(TouchEntryOffset + 0x0, Timestamp); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x8, Padding); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0xc, Index++); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x10, Point.X); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x14, Point.Y); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x18, Point.DiameterX); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x1c, Point.DiameterY); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x20, Point.Angle); + Memory.WriteInt32Unchecked(TouchEntryOffset + 0x24, Padding); + + TouchEntryOffset += HidTouchEntryTouchSize; + } } } } - private void WriteTouchPoints(long BasePosition, params HidTouchPoint[] Points) - { - long TouchScreenOffset = BasePosition + HidTouchScreenOffset; - - long Timestamp = GetTimestamp(); - - CurrTouchEntry = (CurrTouchEntry + 1) % HidEntryCount; - - Ns.Memory.WriteInt64(TouchScreenOffset + 0x0, Timestamp); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x8, HidEntryCount); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x10, CurrTouchEntry); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x18, HidEntryCount - 1); - Ns.Memory.WriteInt64(TouchScreenOffset + 0x20, Timestamp); - - long TouchEntryOffset = TouchScreenOffset + HidTouchHeaderSize; - - TouchEntryOffset += CurrTouchEntry * HidTouchEntrySize; - - Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, CurrTouchSampleCounter++); - Ns.Memory.WriteInt64(TouchEntryOffset + 0x8, Points.Length); - - TouchEntryOffset += HidTouchEntryHeaderSize; - - const int Padding = 0; - - int Index = 0; - - foreach (HidTouchPoint Point in Points) - { - Ns.Memory.WriteInt64(TouchEntryOffset + 0x0, Timestamp); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x8, Padding); - Ns.Memory.WriteInt32(TouchEntryOffset + 0xc, Index++); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x10, Point.X); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x14, Point.Y); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x18, Point.DiameterX); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x1c, Point.DiameterY); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x20, Point.Angle); - Ns.Memory.WriteInt32(TouchEntryOffset + 0x24, Padding); - - TouchEntryOffset += HidTouchEntryTouchSize; - } - } - private long GetTimestamp() { return Environment.TickCount * 19_200; diff --git a/Ryujinx.Core/Loaders/Executable.cs b/Ryujinx.Core/Loaders/Executable.cs index fa204460f6..943b8e5107 100644 --- a/Ryujinx.Core/Loaders/Executable.cs +++ b/Ryujinx.Core/Loaders/Executable.cs @@ -34,7 +34,7 @@ namespace Ryujinx.Core.Loaders if (Exe.Mod0Offset == 0) { - int BssOffset = Exe.DataOffset + Exe.Data.Count; + int BssOffset = Exe.DataOffset + Exe.Data.Length; int BssSize = Exe.BssSize; MapBss(ImageBase + BssOffset, BssSize); @@ -92,18 +92,15 @@ namespace Ryujinx.Core.Loaders private void WriteData( long Position, - IList Data, + byte[] Data, MemoryType Type, 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++) - { - Memory.WriteByte(Position + Index, Data[Index]); - } + AMemoryHelper.WriteBytes(Memory, Position, Data); - Memory.Manager.Reprotect(Position, Data.Count, Perm); + Memory.Manager.Reprotect(Position, Data.Length, Perm); } private void MapBss(long Position, long Size) diff --git a/Ryujinx.Core/Loaders/Executables/IExecutable.cs b/Ryujinx.Core/Loaders/Executables/IExecutable.cs index 73787b1d24..09d0aab236 100644 --- a/Ryujinx.Core/Loaders/Executables/IExecutable.cs +++ b/Ryujinx.Core/Loaders/Executables/IExecutable.cs @@ -1,12 +1,10 @@ -using System.Collections.ObjectModel; - namespace Ryujinx.Core.Loaders.Executables { public interface IExecutable { - ReadOnlyCollection Text { get; } - ReadOnlyCollection RO { get; } - ReadOnlyCollection Data { get; } + byte[] Text { get; } + byte[] RO { get; } + byte[] Data { get; } int Mod0Offset { get; } int TextOffset { get; } diff --git a/Ryujinx.Core/Loaders/Executables/Nro.cs b/Ryujinx.Core/Loaders/Executables/Nro.cs index 3cbc4c5d49..9f4ef59f57 100644 --- a/Ryujinx.Core/Loaders/Executables/Nro.cs +++ b/Ryujinx.Core/Loaders/Executables/Nro.cs @@ -1,18 +1,12 @@ -using System; -using System.Collections.ObjectModel; using System.IO; namespace Ryujinx.Core.Loaders.Executables { class Nro : IExecutable { - private byte[] m_Text; - private byte[] m_RO; - private byte[] m_Data; - - public ReadOnlyCollection Text => Array.AsReadOnly(m_Text); - public ReadOnlyCollection RO => Array.AsReadOnly(m_RO); - public ReadOnlyCollection Data => Array.AsReadOnly(m_Data); + public byte[] Text { get; private set; } + public byte[] RO { get; private set; } + public byte[] Data { get; private set; } public int Mod0Offset { get; private set; } public int TextOffset { get; private set; } @@ -54,9 +48,9 @@ namespace Ryujinx.Core.Loaders.Executables return Reader.ReadBytes(Size); } - m_Text = Read(TextOffset, TextSize); - m_RO = Read(ROOffset, ROSize); - m_Data = Read(DataOffset, DataSize); + Text = Read(TextOffset, TextSize); + RO = Read(ROOffset, ROSize); + Data = Read(DataOffset, DataSize); } } } \ No newline at end of file diff --git a/Ryujinx.Core/Loaders/Executables/Nso.cs b/Ryujinx.Core/Loaders/Executables/Nso.cs index 7b8bf253a7..7341ba6226 100644 --- a/Ryujinx.Core/Loaders/Executables/Nso.cs +++ b/Ryujinx.Core/Loaders/Executables/Nso.cs @@ -1,19 +1,14 @@ using Ryujinx.Core.Loaders.Compression; using System; -using System.Collections.ObjectModel; using System.IO; namespace Ryujinx.Core.Loaders.Executables { class Nso : IExecutable { - private byte[] m_Text; - private byte[] m_RO; - private byte[] m_Data; - - public ReadOnlyCollection Text => Array.AsReadOnly(m_Text); - public ReadOnlyCollection RO => Array.AsReadOnly(m_RO); - public ReadOnlyCollection Data => Array.AsReadOnly(m_Data); + public byte[] Text { get; private set; } + public byte[] RO { get; private set; } + public byte[] Data { get; private set; } public int Mod0Offset { get; private set; } public int TextOffset { get; private set; } @@ -57,9 +52,9 @@ namespace Ryujinx.Core.Loaders.Executables byte[] BuildId = Reader.ReadBytes(0x20); - int TextSize = Reader.ReadInt32(); - int ROSize = Reader.ReadInt32(); - int DataSize = Reader.ReadInt32(); + int TextSize = Reader.ReadInt32(); + int ROSize = Reader.ReadInt32(); + int DataSize = Reader.ReadInt32(); Input.Seek(0x24, SeekOrigin.Current); @@ -82,38 +77,38 @@ namespace Ryujinx.Core.Loaders.Executables //Text segment Input.Seek(TextOffset, SeekOrigin.Begin); - m_Text = Reader.ReadBytes(TextSize); + Text = Reader.ReadBytes(TextSize); if (Flags.HasFlag(NsoFlags.IsTextCompressed) || true) { - m_Text = Lz4.Decompress(m_Text, TextDecSize); + Text = Lz4.Decompress(Text, TextDecSize); } //Read-only data segment Input.Seek(ROOffset, SeekOrigin.Begin); - m_RO = Reader.ReadBytes(ROSize); + RO = Reader.ReadBytes(ROSize); if (Flags.HasFlag(NsoFlags.IsROCompressed) || true) { - m_RO = Lz4.Decompress(m_RO, RODecSize); + RO = Lz4.Decompress(RO, RODecSize); } //Data segment Input.Seek(DataOffset, SeekOrigin.Begin); - m_Data = Reader.ReadBytes(DataSize); + Data = Reader.ReadBytes(DataSize); if (Flags.HasFlag(NsoFlags.IsDataCompressed) || true) { - m_Data = Lz4.Decompress(m_Data, DataDecSize); + Data = Lz4.Decompress(Data, DataDecSize); } - using (MemoryStream Text = new MemoryStream(m_Text)) + using (MemoryStream 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(); } diff --git a/Ryujinx.Core/OsHle/Horizon.cs b/Ryujinx.Core/OsHle/Horizon.cs index a8f5df7c9d..c61e18e98f 100644 --- a/Ryujinx.Core/OsHle/Horizon.cs +++ b/Ryujinx.Core/OsHle/Horizon.cs @@ -52,6 +52,8 @@ namespace Ryujinx.Core.OsHle HidHandle = Handles.GenerateId(HidSharedMem); FontHandle = Handles.GenerateId(new HSharedMem()); + + HidSharedMem.AddVirtualPosition(0); } public void LoadCart(string ExeFsDir, string RomFsFile = null) diff --git a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs index cc26df1082..ebb3dbca04 100644 --- a/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs +++ b/Ryujinx.Core/OsHle/Ipc/IpcMessage.cs @@ -217,16 +217,26 @@ namespace Ryujinx.Core.OsHle.Ipc public long GetSendBuffPtr() { - if (SendBuff.Count > 0 && SendBuff[0].Position != 0) + if (SendBuff.Count > 0 && SendBuff[0].Size != 0) { return SendBuff[0].Position; } - if (PtrBuff.Count > 0 && PtrBuff[0].Position != 0) + if (PtrBuff.Count > 0 && PtrBuff[0].Size != 0) { return PtrBuff[0].Position; } + if (ReceiveBuff.Count > 0 && ReceiveBuff[0].Size != 0) + { + return ReceiveBuff[0].Position; + } + + if (RecvListBuff.Count > 0 && RecvListBuff[0].Size != 0) + { + return RecvListBuff[0].Position; + } + return -1; } } diff --git a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs index 515c15e034..3c0c46fec9 100644 --- a/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs +++ b/Ryujinx.Core/OsHle/Services/Nv/ServiceNvDrv.cs @@ -81,7 +81,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices FileDesc FdData = Context.Ns.Os.Fds.GetData(Fd); - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); Context.ResponseData.Write(0); @@ -139,7 +139,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlBindChannel(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int Fd = Context.Memory.ReadInt32(Position); @@ -148,7 +148,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -174,7 +174,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -207,7 +207,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position); @@ -237,7 +237,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -254,7 +254,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position + 0x82); @@ -269,7 +269,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvHostIoctlCtrlEventWait(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -285,7 +285,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); Context.Memory.WriteInt32(Position, 1); @@ -294,7 +294,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemWriter Writer = new MemWriter(Context.Memory, Position); @@ -314,7 +314,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position); @@ -376,7 +376,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -390,7 +390,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); Context.Memory.WriteInt32(Position + 0, 7); Context.Memory.WriteInt32(Position + 4, 1); @@ -400,14 +400,14 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSetUserData(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); return 0; } private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int Fd = Context.Memory.ReadInt32(Position); @@ -416,7 +416,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position + 0x10); @@ -455,7 +455,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int ClassNum = Context.Memory.ReadInt32(Position + 0); int Flags = Context.Memory.ReadInt32(Position + 4); @@ -467,7 +467,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelZcullBind(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -480,7 +480,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); @@ -494,7 +494,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelSetPriority(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); int Priority = Context.Memory.ReadInt32(Position); @@ -503,7 +503,7 @@ namespace Ryujinx.Core.OsHle.IpcServices.NvServices private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context) { - long Position = Context.Request.PtrBuff[0].Position; + long Position = Context.Request.GetSendBuffPtr(); MemReader Reader = new MemReader(Context.Memory, Position); MemWriter Writer = new MemWriter(Context.Memory, Position + 0xc); diff --git a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs index bf946e4f86..c15f449bf1 100644 --- a/Ryujinx.Core/OsHle/Svc/SvcMemory.cs +++ b/Ryujinx.Core/OsHle/Svc/SvcMemory.cs @@ -55,6 +55,24 @@ namespace Ryujinx.Core.OsHle.Svc long Src = (long)ThreadState.X1; 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); 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 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); Memory.Manager.Unmap(Dst, Size, (int)MemoryType.MappedMemory); @@ -92,9 +128,11 @@ namespace Ryujinx.Core.OsHle.Svc 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); @@ -118,15 +156,26 @@ namespace Ryujinx.Core.OsHle.Svc long Size = (long)ThreadState.X2; 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(Handle); if (SharedMem != null) { + Memory.Manager.Map(Src, Size, (int)MemoryType.SharedMemory, AMemoryPerm.Write); + 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; } @@ -136,14 +185,25 @@ namespace Ryujinx.Core.OsHle.Svc private void SvcUnmapSharedMemory(AThreadState ThreadState) { - int Handle = (int)ThreadState.X0; - long Position = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; + int Handle = (int)ThreadState.X0; + long Src = (long)ThreadState.X1; + 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(Handle); if (HndData != null) { + Memory.Manager.Unmap(Src, Size, (int)MemoryType.SharedMemory); + ThreadState.X0 = 0; } @@ -152,20 +212,41 @@ namespace Ryujinx.Core.OsHle.Svc private void SvcCreateTransferMemory(AThreadState ThreadState) { - long Position = (long)ThreadState.X1; - long Size = (long)ThreadState.X2; - int Perm = (int)ThreadState.X3; + long Src = (long)ThreadState.X1; + long Size = (long)ThreadState.X2; + 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); ThreadState.X1 = (ulong)Handle; 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; + } } } \ No newline at end of file diff --git a/Ryujinx.Core/Switch.cs b/Ryujinx.Core/Switch.cs index dff7802b7d..f7ce109f6f 100644 --- a/Ryujinx.Core/Switch.cs +++ b/Ryujinx.Core/Switch.cs @@ -30,7 +30,7 @@ namespace Ryujinx.Core VFs = new VirtualFs(); - Hid = new Hid(this); + Hid = new Hid(Memory); Statistics = new PerformanceStatistics(); diff --git a/Ryujinx.Tests/Cpu/CpuTest.cs b/Ryujinx.Tests/Cpu/CpuTest.cs index c4f0bbd74a..0b35a7a6c3 100644 --- a/Ryujinx.Tests/Cpu/CpuTest.cs +++ b/Ryujinx.Tests/Cpu/CpuTest.cs @@ -47,7 +47,7 @@ namespace Ryujinx.Tests.Cpu protected void Opcode(uint Opcode) { - Thread.Memory.WriteUInt32(Position, Opcode); + Thread.Memory.WriteUInt32Unchecked(Position, Opcode); Position += 4; } diff --git a/Ryujinx/Ui/Program.cs b/Ryujinx/Ui/Program.cs index b5f8cb9766..b67e52bdc3 100644 --- a/Ryujinx/Ui/Program.cs +++ b/Ryujinx/Ui/Program.cs @@ -10,6 +10,8 @@ namespace Ryujinx { static void Main(string[] args) { + AOptimizations.DisableMemoryChecks = true; + Config.Read(); Console.Title = "Ryujinx Console";