diff options
| author | TSR Berry <20988865+TSRBerry@users.noreply.github.com> | 2023-04-08 01:22:00 +0200 |
|---|---|---|
| committer | Mary <thog@protonmail.com> | 2023-04-27 23:51:14 +0200 |
| commit | cee712105850ac3385cd0091a923438167433f9f (patch) | |
| tree | 4a5274b21d8b7f938c0d0ce18736d3f2993b11b1 /src/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs | |
| parent | cd124bda587ef09668a971fa1cac1c3f0cfc9f21 (diff) | |
Move solution and projects to src
Diffstat (limited to 'src/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs')
| -rw-r--r-- | src/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs b/src/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs new file mode 100644 index 00000000..d695449b --- /dev/null +++ b/src/Ryujinx.HLE/Loaders/Executables/NsoExecutable.cs @@ -0,0 +1,123 @@ +using LibHac.Common.FixedArrays; +using LibHac.Fs; +using LibHac.Loader; +using LibHac.Tools.FsSystem; +using Ryujinx.Common.Logging; +using System; +using System.Text; +using System.Text.RegularExpressions; + +namespace Ryujinx.HLE.Loaders.Executables +{ + partial class NsoExecutable : IExecutable + { + public byte[] Program { get; } + public Span<byte> Text => Program.AsSpan((int)TextOffset, (int)TextSize); + public Span<byte> Ro => Program.AsSpan((int)RoOffset, (int)RoSize); + public Span<byte> Data => Program.AsSpan((int)DataOffset, (int)DataSize); + + public uint TextOffset { get; } + public uint RoOffset { get; } + public uint DataOffset { get; } + public uint BssOffset => DataOffset + (uint)Data.Length; + + public uint TextSize { get; } + public uint RoSize { get; } + public uint DataSize { get; } + public uint BssSize { get; } + + public string Name; + public Array32<byte> BuildId; + + [GeneratedRegex(@"[a-z]:[\\/][ -~]{5,}\.nss", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant)] + private static partial Regex ModuleRegex(); + [GeneratedRegex(@"sdk_version: ([0-9.]*)")] + private static partial Regex FsSdkRegex(); + [GeneratedRegex(@"SDK MW[ -~]*")] + private static partial Regex SdkMwRegex(); + + public NsoExecutable(IStorage inStorage, string name = null) + { + NsoReader reader = new NsoReader(); + + reader.Initialize(inStorage.AsFile(OpenMode.Read)).ThrowIfFailure(); + + 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(); + + Program = new byte[DataOffset + uncompressedSize]; + + TextSize = DecompressSection(reader, NsoReader.SegmentType.Text, TextOffset); + RoSize = DecompressSection(reader, NsoReader.SegmentType.Ro, RoOffset); + DataSize = DecompressSection(reader, NsoReader.SegmentType.Data, DataOffset); + + Name = name; + BuildId = reader.Header.ModuleId; + + PrintRoSectionInfo(); + } + + private uint DecompressSection(NsoReader reader, NsoReader.SegmentType segmentType, uint offset) + { + reader.GetSegmentSize(segmentType, out uint uncompressedSize).ThrowIfFailure(); + + var span = Program.AsSpan((int)offset, (int)uncompressedSize); + + reader.ReadSegment(segmentType, span).ThrowIfFailure(); + + return uncompressedSize; + } + + private void PrintRoSectionInfo() + { + string rawTextBuffer = Encoding.ASCII.GetString(Ro); + StringBuilder stringBuilder = new StringBuilder(); + + string modulePath = null; + + if (BitConverter.ToInt32(Ro.Slice(0, 4)) == 0) + { + int length = BitConverter.ToInt32(Ro.Slice(4, 4)); + if (length > 0) + { + modulePath = Encoding.UTF8.GetString(Ro.Slice(8, length)); + } + } + + if (string.IsNullOrEmpty(modulePath)) + { + Match moduleMatch = ModuleRegex().Match(rawTextBuffer); + if (moduleMatch.Success) + { + modulePath = moduleMatch.Value; + } + } + + stringBuilder.AppendLine($" Module: {modulePath}"); + + Match fsSdkMatch = FsSdkRegex().Match(rawTextBuffer); + if (fsSdkMatch.Success) + { + stringBuilder.AppendLine($" FS SDK Version: {fsSdkMatch.Value.Replace("sdk_version: ", "")}"); + } + + MatchCollection sdkMwMatches = SdkMwRegex().Matches(rawTextBuffer); + if (sdkMwMatches.Count != 0) + { + string libHeader = " SDK Libraries: "; + string libContent = string.Join($"\n{new string(' ', libHeader.Length)}", sdkMwMatches); + + stringBuilder.AppendLine($"{libHeader}{libContent}"); + } + + if (stringBuilder.Length > 0) + { + Logger.Info?.Print(LogClass.Loader, $"{Name}:\n{stringBuilder.ToString().TrimEnd('\r', '\n')}"); + } + } + } +}
\ No newline at end of file |
