diff --git a/Ryujinx.HLE/HOS/Horizon.cs b/Ryujinx.HLE/HOS/Horizon.cs index ee8c2a20e8..5f75a8740b 100644 --- a/Ryujinx.HLE/HOS/Horizon.cs +++ b/Ryujinx.HLE/HOS/Horizon.cs @@ -271,7 +271,7 @@ namespace Ryujinx.HLE.HOS public void LoadKip(string kipFile) { - using (FileStream fs = new FileStream(kipFile, FileMode.Open)) + using (IStorage fs = new LocalStorage(kipFile, FileAccess.Read)) { ProgramLoader.LoadKernelInitalProcess(this, new KernelInitialProcess(fs)); } @@ -544,8 +544,8 @@ namespace Ryujinx.HLE.HOS Logger.PrintInfo(LogClass.Loader, $"Loading {file.Name}..."); codeFs.OpenFile(out IFile nsoFile, file.FullPath.ToU8Span(), OpenMode.Read).ThrowIfFailure(); - - NxStaticObject staticObject = new NxStaticObject(nsoFile.AsStream()); + + NxStaticObject staticObject = new NxStaticObject(nsoFile.AsStorage()); staticObjects.Add(staticObject); } @@ -569,12 +569,12 @@ namespace Ryujinx.HLE.HOS bool isNro = Path.GetExtension(filePath).ToLower() == ".nro"; - FileStream input = new FileStream(filePath, FileMode.Open); IExecutable staticObject; if (isNro) { + FileStream input = new FileStream(filePath, FileMode.Open); NxRelocatableObject obj = new NxRelocatableObject(input); staticObject = obj; @@ -648,7 +648,7 @@ namespace Ryujinx.HLE.HOS } else { - staticObject = new NxStaticObject(input); + staticObject = new NxStaticObject(new LocalStorage(filePath, FileAccess.Read)); } ContentManager.LoadEntries(Device); diff --git a/Ryujinx.HLE/HOS/ProgramLoader.cs b/Ryujinx.HLE/HOS/ProgramLoader.cs index 19c77380d4..efe196b7a4 100644 --- a/Ryujinx.HLE/HOS/ProgramLoader.cs +++ b/Ryujinx.HLE/HOS/ProgramLoader.cs @@ -6,6 +6,7 @@ using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Kernel.Process; using Ryujinx.HLE.Loaders.Executables; using Ryujinx.HLE.Loaders.Npdm; +using LibHac; namespace Ryujinx.HLE.HOS { @@ -288,7 +289,6 @@ namespace Ryujinx.HLE.HOS } size = BitUtils.AlignUp(size, KMemoryManager.PageSize); - return process.MemoryManager.SetProcessMemoryPermission(address, size, permission); } @@ -306,6 +306,7 @@ namespace Ryujinx.HLE.HOS return result; } + return SetProcessMemoryPermission(dataStart, end - dataStart, MemoryPermission.ReadAndWrite); } } diff --git a/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs b/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs index d6a1cb66bd..0e60472b0e 100644 --- a/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs +++ b/Ryujinx.HLE/Loaders/Executables/KernelInitialProcess.cs @@ -1,43 +1,46 @@ using Ryujinx.HLE.Loaders.Compression; using System.IO; +using LibHac; +using LibHac.Fs; namespace Ryujinx.HLE.Loaders.Executables { class KernelInitialProcess : IExecutable { - public string Name { get; private set; } + Kip kip; + public string Name => kip.Header.Name; - public ulong TitleId { get; private set; } + public ulong TitleId => kip.Header.TitleId; - public int ProcessCategory { get; private set; } + public int ProcessCategory => kip.Header.ProcessCategory; - public byte MainThreadPriority { get; private set; } - public byte DefaultProcessorId { get; private set; } + public byte MainThreadPriority => kip.Header.MainThreadPriority; + public byte DefaultProcessorId => kip.Header.DefaultCore; + + public bool Is64Bits => (kip.Header.Flags & 0x08) != 0; + public bool Addr39Bits => (kip.Header.Flags & 0x10) != 0; + public bool IsService => (kip.Header.Flags & 0x20) != 0; - public bool Is64Bits { get; private set; } - public bool Addr39Bits { get; private set; } - public bool IsService { get; private set; } public byte[] Text { get; private set; } - public byte[] Ro { get; private set; } + public byte[] Ro { get; private set; } public byte[] Data { get; private set; } - public int TextOffset { get; private set; } - public int RoOffset { get; private set; } - public int DataOffset { get; private set; } - public int BssOffset { get; private set; } - public int BssSize { get; private set; } + public int TextOffset => kip.Header.Sections[0].OutOffset; + public int RoOffset => kip.Header.Sections[1].OutOffset; + public int DataOffset => kip.Header.Sections[2].OutOffset; + public int BssOffset => kip.Header.Sections[3].OutOffset; + public int BssSize => kip.Header.Sections[3].DecompressedSize; - public int MainThreadStackSize { get; private set; } - - public int[] Capabilities { get; private set; } + public int MainThreadStackSize => kip.Header.Sections[1].Attribute; + public int[] Capabilities { get; set; } private struct SegmentHeader { - public int Offset { get; private set; } + public int Offset { get; private set; } public int DecompressedSize { get; private set; } - public int CompressedSize { get; private set; } - public int Attribute { get; private set; } + public int CompressedSize { get; private set; } + public int Attribute { get; private set; } public SegmentHeader( int offset, @@ -45,103 +48,28 @@ namespace Ryujinx.HLE.Loaders.Executables int compressedSize, int attribute) { - Offset = offset; + Offset = offset; DecompressedSize = decompressedSize; - CompressedSize = compressedSize; - Attribute = attribute; + CompressedSize = compressedSize; + Attribute = attribute; } } - public KernelInitialProcess(Stream input) + public KernelInitialProcess(IStorage inStorage) { - BinaryReader reader = new BinaryReader(input); - - string magic = ReadString(reader, 4); - - if (magic != "KIP1") - { - - } - - Name = ReadString(reader, 12); - - TitleId = reader.ReadUInt64(); - - ProcessCategory = reader.ReadInt32(); - - MainThreadPriority = reader.ReadByte(); - DefaultProcessorId = reader.ReadByte(); - - byte reserved = reader.ReadByte(); - byte flags = reader.ReadByte(); - - Is64Bits = (flags & 0x08) != 0; - Addr39Bits = (flags & 0x10) != 0; - IsService = (flags & 0x20) != 0; - - SegmentHeader[] segments = new SegmentHeader[6]; - - for (int index = 0; index < segments.Length; index++) - { - segments[index] = new SegmentHeader( - reader.ReadInt32(), - reader.ReadInt32(), - reader.ReadInt32(), - reader.ReadInt32()); - } - - TextOffset = segments[0].Offset; - RoOffset = segments[1].Offset; - DataOffset = segments[2].Offset; - BssOffset = segments[3].Offset; - BssSize = segments[3].DecompressedSize; - - MainThreadStackSize = segments[1].Attribute; - + kip = new Kip(inStorage); Capabilities = new int[32]; for (int index = 0; index < Capabilities.Length; index++) { - Capabilities[index] = reader.ReadInt32(); + Capabilities[index] = System.BitConverter.ToInt32(kip.Header.Capabilities, index * 4); } - input.Seek(0x100, SeekOrigin.Begin); - Text = ReadSegment(segments[0], input); - Ro = ReadSegment(segments[1], input); - Data = ReadSegment(segments[2], input); + Text = kip.DecompressSection(0); + Ro = kip.DecompressSection(1); + Data = kip.DecompressSection(2); } - private byte[] ReadSegment(SegmentHeader header, Stream input) - { - byte[] data = new byte[header.DecompressedSize]; - - input.Read(data, 0, header.CompressedSize); - - BackwardsLz.DecompressInPlace(data, header.CompressedSize); - - return data; - } - - private static string ReadString(BinaryReader reader, int maxSize) - { - string value = string.Empty; - - for (int index = 0; index < maxSize; index++) - { - char chr = (char)reader.ReadByte(); - - if (chr == '\0') - { - reader.BaseStream.Seek(maxSize - index - 1, SeekOrigin.Current); - - break; - } - - value += chr; - } - - return value; - } } } \ No newline at end of file diff --git a/Ryujinx.HLE/Loaders/Executables/NxStaticObject.cs b/Ryujinx.HLE/Loaders/Executables/NxStaticObject.cs index 03c3b39a47..d19347785f 100644 --- a/Ryujinx.HLE/Loaders/Executables/NxStaticObject.cs +++ b/Ryujinx.HLE/Loaders/Executables/NxStaticObject.cs @@ -1,21 +1,24 @@ using Ryujinx.HLE.Loaders.Compression; using System; using System.IO; +using LibHac.Fs; +using LibHac; namespace Ryujinx.HLE.Loaders.Executables { class NxStaticObject : IExecutable { + Nso nso; + public byte[] Text { get; private set; } public byte[] Ro { get; private set; } public byte[] Data { get; private set; } - public int TextOffset { get; private set; } - public int RoOffset { get; private set; } - public int DataOffset { get; private set; } - public int BssSize { get; private set; } - + public int TextOffset => (int)nso.Sections[0].MemoryOffset; + public int RoOffset => (int)nso.Sections[1].MemoryOffset; + public int DataOffset => (int)nso.Sections[2].MemoryOffset; public int BssOffset => DataOffset + Data.Length; + public int BssSize => (int)nso.BssSize; [Flags] private enum NsoFlags @@ -28,82 +31,13 @@ namespace Ryujinx.HLE.Loaders.Executables HasDataHash = 1 << 5 } - public NxStaticObject(Stream input) + public NxStaticObject(IStorage inStorage) { - BinaryReader reader = new BinaryReader(input); - - input.Seek(0, SeekOrigin.Begin); - - int nsoMagic = reader.ReadInt32(); - int version = reader.ReadInt32(); - int reserved = reader.ReadInt32(); - int flagsMsk = reader.ReadInt32(); - int textOffset = reader.ReadInt32(); - int textMemOffset = reader.ReadInt32(); - int textDecSize = reader.ReadInt32(); - int modNameOffset = reader.ReadInt32(); - int roOffset = reader.ReadInt32(); - int roMemOffset = reader.ReadInt32(); - int roDecSize = reader.ReadInt32(); - int modNameSize = reader.ReadInt32(); - int dataOffset = reader.ReadInt32(); - int dataMemOffset = reader.ReadInt32(); - int dataDecSize = reader.ReadInt32(); - int bssSize = reader.ReadInt32(); - - byte[] buildId = reader.ReadBytes(0x20); - - int textSize = reader.ReadInt32(); - int roSize = reader.ReadInt32(); - int dataSize = reader.ReadInt32(); - - input.Seek(0x24, SeekOrigin.Current); - - int dynStrOffset = reader.ReadInt32(); - int dynStrSize = reader.ReadInt32(); - int dynSymOffset = reader.ReadInt32(); - int dynSymSize = reader.ReadInt32(); - - byte[] textHash = reader.ReadBytes(0x20); - byte[] roHash = reader.ReadBytes(0x20); - byte[] dataHash = reader.ReadBytes(0x20); - - NsoFlags flags = (NsoFlags)flagsMsk; - - TextOffset = textMemOffset; - RoOffset = roMemOffset; - DataOffset = dataMemOffset; - BssSize = bssSize; - - // Text segment - input.Seek(textOffset, SeekOrigin.Begin); - - Text = reader.ReadBytes(textSize); - - if (flags.HasFlag(NsoFlags.IsTextCompressed) && textSize != 0) - { - Text = Lz4.Decompress(Text, textDecSize); - } - - // Read-only data segment - input.Seek(roOffset, SeekOrigin.Begin); - - Ro = reader.ReadBytes(roSize); - - if (flags.HasFlag(NsoFlags.IsRoCompressed) && roSize != 0) - { - Ro = Lz4.Decompress(Ro, roDecSize); - } - - // Data segment - input.Seek(dataOffset, SeekOrigin.Begin); - - Data = reader.ReadBytes(dataSize); - - if (flags.HasFlag(NsoFlags.IsDataCompressed) && dataSize != 0) - { - Data = Lz4.Decompress(Data, dataDecSize); - } + nso = new Nso(inStorage); + Text = nso.Sections[0].DecompressSection(); + Ro = nso.Sections[1].DecompressSection(); + Data = nso.Sections[2].DecompressSection(); } + } } \ No newline at end of file