NsoExecutable.cs 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. using LibHac.Common;
  2. using LibHac.Fs;
  3. using LibHac.FsSystem;
  4. using LibHac.Loader;
  5. using System;
  6. namespace Ryujinx.HLE.Loaders.Executables
  7. {
  8. class NsoExecutable : IExecutable
  9. {
  10. public byte[] Program { get; }
  11. public Span<byte> Text => Program.AsSpan().Slice(TextOffset, TextSize);
  12. public Span<byte> Ro => Program.AsSpan().Slice(RoOffset, RoSize);
  13. public Span<byte> Data => Program.AsSpan().Slice(DataOffset, DataSize);
  14. public int TextOffset { get; }
  15. public int RoOffset { get; }
  16. public int DataOffset { get; }
  17. public int BssOffset => DataOffset + Data.Length;
  18. public int TextSize { get; }
  19. public int RoSize { get; }
  20. public int DataSize { get; }
  21. public int BssSize { get; }
  22. public string Name;
  23. public Buffer32 BuildId;
  24. public NsoExecutable(IStorage inStorage, string name = null)
  25. {
  26. NsoReader reader = new NsoReader();
  27. reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure();
  28. TextOffset = (int)reader.Header.Segments[0].MemoryOffset;
  29. RoOffset = (int)reader.Header.Segments[1].MemoryOffset;
  30. DataOffset = (int)reader.Header.Segments[2].MemoryOffset;
  31. BssSize = (int)reader.Header.BssSize;
  32. reader.GetSegmentSize(NsoReader.SegmentType.Data, out uint uncompressedSize).ThrowIfFailure();
  33. Program = new byte[DataOffset + uncompressedSize];
  34. TextSize = DecompressSection(reader, NsoReader.SegmentType.Text, TextOffset, Program);
  35. RoSize = DecompressSection(reader, NsoReader.SegmentType.Ro, RoOffset, Program);
  36. DataSize = DecompressSection(reader, NsoReader.SegmentType.Data, DataOffset, Program);
  37. Name = name;
  38. BuildId = reader.Header.ModuleId;
  39. }
  40. private static int DecompressSection(NsoReader reader, NsoReader.SegmentType segmentType, int offset, byte[] Program)
  41. {
  42. reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure();
  43. var span = Program.AsSpan().Slice(offset, (int)uncompressedSize);
  44. reader.ReadSegment(segmentType, span).ThrowIfFailure();
  45. return (int)uncompressedSize;
  46. }
  47. }
  48. }