KipExecutable.cs 3.3 KB

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