using Ryujinx.HLE.Loaders.Compression; using System.IO; namespace Ryujinx.HLE.Loaders.Executables { class KernelInitialProcess : IExecutable { public string Name { get; private set; } public ulong TitleId { get; private set; } public int ProcessCategory { get; private set; } public byte MainThreadPriority { get; private set; } public byte DefaultProcessorId { get; private set; } 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[] 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 MainThreadStackSize { get; private set; } public int[] Capabilities { get; private set; } private struct SegmentHeader { 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 SegmentHeader( int offset, int decompressedSize, int compressedSize, int attribute) { Offset = offset; DecompressedSize = decompressedSize; CompressedSize = compressedSize; Attribute = attribute; } } public KernelInitialProcess(Stream input) { 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; Capabilities = new int[32]; for (int index = 0; index < Capabilities.Length; index++) { Capabilities[index] = reader.ReadInt32(); } input.Seek(0x100, SeekOrigin.Begin); Text = ReadSegment(segments[0], input); Ro = ReadSegment(segments[1], input); Data = ReadSegment(segments[2], input); } 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; } } }