diff --git a/Ryujinx.Common/Utilities/BitUtils.cs b/Ryujinx.Common/Utilities/BitUtils.cs index 5f70f742a0..4ce7da6b53 100644 --- a/Ryujinx.Common/Utilities/BitUtils.cs +++ b/Ryujinx.Common/Utilities/BitUtils.cs @@ -4,6 +4,11 @@ namespace Ryujinx.Common { private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }; + public static uint AlignUp(uint value, int size) + { + return (uint)AlignUp((int)value, size); + } + public static int AlignUp(int value, int size) { return (value + (size - 1)) & -size; @@ -19,6 +24,11 @@ namespace Ryujinx.Common return (value + (size - 1)) & -(long)size; } + public static uint AlignDown(uint value, int size) + { + return (uint)AlignDown((int)value, size); + } + public static int AlignDown(int value, int size) { return value & -size; diff --git a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs index d19901695c..429c23e33e 100644 --- a/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs +++ b/Ryujinx.HLE/HOS/Kernel/Process/KProcess.cs @@ -1072,7 +1072,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Process private bool InvalidAccessHandler(ulong va) { - KernelStatic.GetCurrentThread().PrintGuestStackTrace(); + KernelStatic.GetCurrentThread()?.PrintGuestStackTrace(); Logger.Error?.Print(LogClass.Cpu, $"Invalid memory access at virtual address 0x{va:X16}."); diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs index 637c3efc24..79f8af7a84 100644 --- a/Ryujinx.HLE/HOS/ProgramLoader.cs +++ b/Ryujinx.HLE/HOS/ProgramLoader.cs @@ -21,16 +21,16 @@ namespace Ryujinx.HLE.HOS public static bool LoadKip(KernelContext context, KipExecutable kip) { - int endOffset = kip.DataOffset + kip.Data.Length; + uint endOffset = kip.DataOffset + (uint)kip.Data.Length; if (kip.BssSize != 0) { endOffset = kip.BssOffset + kip.BssSize; } - int codeSize = BitUtils.AlignUp(kip.TextOffset + endOffset, KMemoryManager.PageSize); + uint codeSize = BitUtils.AlignUp(kip.TextOffset + endOffset, KMemoryManager.PageSize); - int codePagesCount = codeSize / KMemoryManager.PageSize; + int codePagesCount = (int)(codeSize / KMemoryManager.PageSize); ulong codeBaseAddress = kip.Is64BitAddressSpace ? 0x8000000UL : 0x200000UL; @@ -124,35 +124,31 @@ namespace Ryujinx.HLE.HOS return true; } - public static bool LoadNsos( - KernelContext context, - Npdm metaData, - byte[] arguments = null, - params IExecutable[] executables) + public static bool LoadNsos(KernelContext context, Npdm metaData, byte[] arguments = null, params IExecutable[] executables) { ulong argsStart = 0; - int argsSize = 0; + uint argsSize = 0; ulong codeStart = metaData.Is64Bit ? 0x8000000UL : 0x200000UL; - int codeSize = 0; + uint codeSize = 0; ulong[] nsoBase = new ulong[executables.Length]; for (int index = 0; index < executables.Length; index++) { - IExecutable staticObject = executables[index]; + IExecutable nso = executables[index]; - int textEnd = staticObject.TextOffset + staticObject.Text.Length; - int roEnd = staticObject.RoOffset + staticObject.Ro.Length; - int dataEnd = staticObject.DataOffset + staticObject.Data.Length + staticObject.BssSize; + uint textEnd = nso.TextOffset + (uint)nso.Text.Length; + uint roEnd = nso.RoOffset + (uint)nso.Ro.Length; + uint dataEnd = nso.DataOffset + (uint)nso.Data.Length + nso.BssSize; - int nsoSize = textEnd; + uint nsoSize = textEnd; - if ((uint)nsoSize < (uint)roEnd) + if (nsoSize < roEnd) { nsoSize = roEnd; } - if ((uint)nsoSize < (uint)dataEnd) + if (nsoSize < dataEnd) { nsoSize = dataEnd; } @@ -167,16 +163,16 @@ namespace Ryujinx.HLE.HOS { argsStart = (ulong)codeSize; - argsSize = BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize); + argsSize = (uint)BitUtils.AlignDown(arguments.Length * 2 + ArgsTotalSize - 1, KMemoryManager.PageSize); codeSize += argsSize; } } PtcProfiler.StaticCodeStart = codeStart; - PtcProfiler.StaticCodeSize = codeSize; + PtcProfiler.StaticCodeSize = (int)codeSize; - int codePagesCount = codeSize / KMemoryManager.PageSize; + int codePagesCount = (int)(codeSize / KMemoryManager.PageSize); int personalMmHeapPagesCount = metaData.PersonalMmHeapSize / KMemoryManager.PageSize; @@ -284,7 +280,7 @@ namespace Ryujinx.HLE.HOS process.CpuMemory.Write(roStart, image.Ro); process.CpuMemory.Write(dataStart, image.Data); - MemoryHelper.FillWithZeros(process.CpuMemory, (long)bssStart, image.BssSize); + process.CpuMemory.Fill(bssStart, image.BssSize, 0); KernelResult SetProcessMemoryPermission(ulong address, ulong size, KMemoryPermission permission) { diff --git a/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs b/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs index c78634faf7..f31d8bded7 100644 --- a/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs +++ b/Ryujinx.HLE/HOS/Services/Ro/IRoInterface.cs @@ -187,7 +187,7 @@ namespace Ryujinx.HLE.HOS.Services.Ro return ResultCode.InvalidNro; } - int totalSize = nro.Text.Length + nro.Ro.Length + nro.Data.Length + nro.BssSize; + uint totalSize = (uint)nro.Text.Length + (uint)nro.Ro.Length + (uint)nro.Data.Length + nro.BssSize; // Apply patches context.Device.FileSystem.ModLoader.ApplyNroPatches(nro); diff --git a/Ryujinx.HLE/Loaders/Executables/IExecutable.cs b/Ryujinx.HLE/Loaders/Executables/IExecutable.cs index 76a550df71..27479efe16 100644 --- a/Ryujinx.HLE/Loaders/Executables/IExecutable.cs +++ b/Ryujinx.HLE/Loaders/Executables/IExecutable.cs @@ -4,15 +4,15 @@ namespace Ryujinx.HLE.Loaders.Executables { interface IExecutable { - byte[] Program { get; } + byte[] Program { get; } Span Text { get; } Span Ro { get; } Span Data { get; } - int TextOffset { get; } - int RoOffset { get; } - int DataOffset { get; } - int BssOffset { get; } - int BssSize { get; } + uint TextOffset { get; } + uint RoOffset { get; } + uint DataOffset { get; } + uint BssOffset { get; } + uint BssSize { get; } } } \ No newline at end of file diff --git a/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs b/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs index 292e360b53..12730cd349 100644 --- a/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs +++ b/Ryujinx.HLE/Loaders/Executables/KipExecutable.cs @@ -7,19 +7,19 @@ namespace Ryujinx.HLE.Loaders.Executables class KipExecutable : IExecutable { public byte[] Program { get; } - public Span Text => Program.AsSpan().Slice(TextOffset, TextSize); - public Span Ro => Program.AsSpan().Slice(RoOffset, RoSize); - public Span Data => Program.AsSpan().Slice(DataOffset, DataSize); + public Span Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize); + public Span Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize); + public Span Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize); - public int TextOffset { get; } - public int RoOffset { get; } - public int DataOffset { get; } - public int BssOffset { get; } + public uint TextOffset { get; } + public uint RoOffset { get; } + public uint DataOffset { get; } + public uint BssOffset { get; } - public int TextSize { get; } - public int RoSize { get; } - public int DataSize { get; } - public int BssSize { get; } + public uint TextSize { get; } + public uint RoSize { get; } + public uint DataSize { get; } + public uint BssSize { get; } public int[] Capabilities { get; } public bool UsesSecureMemory { get; } @@ -38,11 +38,11 @@ namespace Ryujinx.HLE.Loaders.Executables reader.Initialize(inStorage).ThrowIfFailure(); - TextOffset = reader.Segments[0].MemoryOffset; - RoOffset = reader.Segments[1].MemoryOffset; - DataOffset = reader.Segments[2].MemoryOffset; - BssOffset = reader.Segments[3].MemoryOffset; - BssSize = reader.Segments[3].Size; + TextOffset = (uint)reader.Segments[0].MemoryOffset; + RoOffset = (uint)reader.Segments[1].MemoryOffset; + DataOffset = (uint)reader.Segments[2].MemoryOffset; + BssOffset = (uint)reader.Segments[3].MemoryOffset; + BssSize = (uint)reader.Segments[3].Size; StackSize = reader.StackSize; @@ -71,15 +71,15 @@ namespace Ryujinx.HLE.Loaders.Executables DataSize = DecompressSection(reader, KipReader.SegmentType.Data, DataOffset, Program); } - private static int DecompressSection(KipReader reader, KipReader.SegmentType segmentType, int offset, byte[] program) + private static uint DecompressSection(KipReader reader, KipReader.SegmentType segmentType, uint offset, byte[] program) { reader.GetSegmentSize(segmentType, out int uncompressedSize).ThrowIfFailure(); - var span = program.AsSpan().Slice(offset, uncompressedSize); + var span = program.AsSpan().Slice((int)offset, uncompressedSize); reader.ReadSegment(segmentType, span).ThrowIfFailure(); - return uncompressedSize; + return (uint)uncompressedSize; } } } \ No newline at end of file diff --git a/Ryujinx.HLE/Loaders/Executables/NroExecutable.cs b/Ryujinx.HLE/Loaders/Executables/NroExecutable.cs index b7a887b7cb..7a9d04ec72 100644 --- a/Ryujinx.HLE/Loaders/Executables/NroExecutable.cs +++ b/Ryujinx.HLE/Loaders/Executables/NroExecutable.cs @@ -7,18 +7,18 @@ namespace Ryujinx.HLE.Loaders.Executables class NroExecutable : Nro, IExecutable { public byte[] Program { get; } - public Span Text => Program.AsSpan().Slice(TextOffset, (int)Header.NroSegments[0].Size); - public Span Ro => Program.AsSpan().Slice(RoOffset, (int)Header.NroSegments[1].Size); - public Span Data => Program.AsSpan().Slice(DataOffset, (int)Header.NroSegments[2].Size); + public Span Text => Program.AsSpan().Slice((int)TextOffset, (int)Header.NroSegments[0].Size); + public Span Ro => Program.AsSpan().Slice((int)RoOffset, (int)Header.NroSegments[1].Size); + public Span Data => Program.AsSpan().Slice((int)DataOffset, (int)Header.NroSegments[2].Size); - public int TextOffset => (int)Header.NroSegments[0].FileOffset; - public int RoOffset => (int)Header.NroSegments[1].FileOffset; - public int DataOffset => (int)Header.NroSegments[2].FileOffset; - public int BssOffset => DataOffset + Data.Length; - public int BssSize => (int)Header.BssSize; + public uint TextOffset => Header.NroSegments[0].FileOffset; + public uint RoOffset => Header.NroSegments[1].FileOffset; + public uint DataOffset => Header.NroSegments[2].FileOffset; + public uint BssOffset => DataOffset + (uint)Data.Length; + public uint BssSize => Header.BssSize; - public int Mod0Offset => Start.Mod0Offset; - public int FileSize => (int)Header.Size; + public uint Mod0Offset => (uint)Start.Mod0Offset; + public uint FileSize => Header.Size; public ulong SourceAddress { get; private set; } public ulong BssAddress { get; private set; } diff --git a/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs b/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs index c9741417c6..2b9f6802e5 100644 --- a/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs +++ b/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs @@ -13,19 +13,19 @@ namespace Ryujinx.HLE.Loaders.Executables class NsoExecutable : IExecutable { public byte[] Program { get; } - public Span Text => Program.AsSpan().Slice(TextOffset, TextSize); - public Span Ro => Program.AsSpan().Slice(RoOffset, RoSize); - public Span Data => Program.AsSpan().Slice(DataOffset, DataSize); + public Span Text => Program.AsSpan().Slice((int)TextOffset, (int)TextSize); + public Span Ro => Program.AsSpan().Slice((int)RoOffset, (int)RoSize); + public Span Data => Program.AsSpan().Slice((int)DataOffset, (int)DataSize); - public int TextOffset { get; } - public int RoOffset { get; } - public int DataOffset { get; } - public int BssOffset => DataOffset + Data.Length; + public uint TextOffset { get; } + public uint RoOffset { get; } + public uint DataOffset { get; } + public uint BssOffset => DataOffset + (uint)Data.Length; - public int TextSize { get; } - public int RoSize { get; } - public int DataSize { get; } - public int BssSize { get; } + public uint TextSize { get; } + public uint RoSize { get; } + public uint DataSize { get; } + public uint BssSize { get; } public string Name; public Buffer32 BuildId; @@ -36,10 +36,10 @@ namespace Ryujinx.HLE.Loaders.Executables reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure(); - TextOffset = (int)reader.Header.Segments[0].MemoryOffset; - RoOffset = (int)reader.Header.Segments[1].MemoryOffset; - DataOffset = (int)reader.Header.Segments[2].MemoryOffset; - BssSize = (int)reader.Header.BssSize; + TextOffset = reader.Header.Segments[0].MemoryOffset; + RoOffset = reader.Header.Segments[1].MemoryOffset; + DataOffset = reader.Header.Segments[2].MemoryOffset; + BssSize = reader.Header.BssSize; reader.GetSegmentSize(NsoReader.SegmentType.Data, out uint uncompressedSize).ThrowIfFailure(); @@ -55,21 +55,21 @@ namespace Ryujinx.HLE.Loaders.Executables PrintRoSectionInfo(); } - private int DecompressSection(NsoReader reader, NsoReader.SegmentType segmentType, int offset) + private uint DecompressSection(NsoReader reader, NsoReader.SegmentType segmentType, uint offset) { reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure(); - var span = Program.AsSpan().Slice(offset, (int)uncompressedSize); + var span = Program.AsSpan().Slice((int)offset, (int)uncompressedSize); reader.ReadSegment(segmentType, span).ThrowIfFailure(); - return (int)uncompressedSize; + return uncompressedSize; } private void PrintRoSectionInfo() { byte[] roBuffer = Ro.ToArray(); - string rawTextBuffer = Encoding.ASCII.GetString(roBuffer, 0, RoSize); + string rawTextBuffer = Encoding.ASCII.GetString(roBuffer, 0, (int)RoSize); StringBuilder stringBuilder = new StringBuilder(); int zero = BitConverter.ToInt32(roBuffer, 0); diff --git a/Ryujinx.Memory/IVirtualMemoryManager.cs b/Ryujinx.Memory/IVirtualMemoryManager.cs index e7e1a9780b..cd271a5f94 100644 --- a/Ryujinx.Memory/IVirtualMemoryManager.cs +++ b/Ryujinx.Memory/IVirtualMemoryManager.cs @@ -13,6 +13,18 @@ namespace Ryujinx.Memory void Write(ulong va, T value) where T : unmanaged; void Write(ulong va, ReadOnlySpan data); + void Fill(ulong va, ulong size, byte value) + { + const int MaxChunkSize = 1 << 30; + + for (ulong subOffset = 0; subOffset < size; subOffset += MaxChunkSize) + { + int copySize = (int)Math.Min(MaxChunkSize, size - subOffset); + + GetWritableRegion(va + subOffset, copySize).Memory.Span.Fill(0); + } + } + ReadOnlySpan GetSpan(ulong va, int size, bool tracked = false); WritableRegion GetWritableRegion(ulong va, int size); ref T GetRef(ulong va) where T : unmanaged;