/ src / Ryujinx.HLE / Loaders / Executables / KipExecutable.cs
KipExecutable.cs
 1  using LibHac.Common;
 2  using LibHac.Fs;
 3  using LibHac.Kernel;
 4  using System;
 5  
 6  namespace Ryujinx.HLE.Loaders.Executables
 7  {
 8      class KipExecutable : IExecutable
 9      {
10          public byte[] Program { get; }
11          public Span<byte> Text => Program.AsSpan((int)TextOffset, (int)TextSize);
12          public Span<byte> Ro => Program.AsSpan((int)RoOffset, (int)RoSize);
13          public Span<byte> Data => Program.AsSpan((int)DataOffset, (int)DataSize);
14  
15          public uint TextOffset { get; }
16          public uint RoOffset { get; }
17          public uint DataOffset { get; }
18          public uint BssOffset { get; }
19  
20          public uint TextSize { get; }
21          public uint RoSize { get; }
22          public uint DataSize { get; }
23          public uint BssSize { get; }
24  
25          public uint[] Capabilities { get; }
26          public bool UsesSecureMemory { get; }
27          public bool Is64BitAddressSpace { get; }
28          public bool Is64Bit { get; }
29          public ulong ProgramId { get; }
30          public byte Priority { get; }
31          public int StackSize { get; }
32          public byte IdealCoreId { get; }
33          public int Version { get; }
34          public string Name { get; }
35  
36          public KipExecutable(in SharedRef<IStorage> inStorage)
37          {
38              KipReader reader = new();
39  
40              reader.Initialize(in inStorage).ThrowIfFailure();
41  
42              TextOffset = (uint)reader.Segments[0].MemoryOffset;
43              RoOffset = (uint)reader.Segments[1].MemoryOffset;
44              DataOffset = (uint)reader.Segments[2].MemoryOffset;
45              BssOffset = (uint)reader.Segments[3].MemoryOffset;
46              BssSize = (uint)reader.Segments[3].Size;
47  
48              StackSize = reader.StackSize;
49  
50              UsesSecureMemory = reader.UsesSecureMemory;
51              Is64BitAddressSpace = reader.Is64BitAddressSpace;
52              Is64Bit = reader.Is64Bit;
53  
54              ProgramId = reader.ProgramId;
55              Priority = reader.Priority;
56              IdealCoreId = reader.IdealCoreId;
57              Version = reader.Version;
58              Name = reader.Name.ToString();
59  
60              Capabilities = new uint[32];
61  
62              for (int index = 0; index < Capabilities.Length; index++)
63              {
64                  Capabilities[index] = reader.Capabilities[index];
65              }
66  
67              reader.GetSegmentSize(KipReader.SegmentType.Data, out int uncompressedSize).ThrowIfFailure();
68              Program = new byte[DataOffset + uncompressedSize];
69  
70              TextSize = DecompressSection(reader, KipReader.SegmentType.Text, TextOffset, Program);
71              RoSize = DecompressSection(reader, KipReader.SegmentType.Ro, RoOffset, Program);
72              DataSize = DecompressSection(reader, KipReader.SegmentType.Data, DataOffset, Program);
73          }
74  
75          private static uint DecompressSection(KipReader reader, KipReader.SegmentType segmentType, uint offset, byte[] program)
76          {
77              reader.GetSegmentSize(segmentType, out int uncompressedSize).ThrowIfFailure();
78  
79              var span = program.AsSpan((int)offset, uncompressedSize);
80  
81              reader.ReadSegment(segmentType, span).ThrowIfFailure();
82  
83              return (uint)uncompressedSize;
84          }
85      }
86  }