Rename Ryujinx.Core to Ryujinx.HLE and add a separate project for a future LLE implementation
This commit is contained in:
parent
518fe799da
commit
76f3b1b3a4
248 changed files with 2266 additions and 2244 deletions
78
Ryujinx.HLE/Loaders/Compression/Lz4.cs
Normal file
78
Ryujinx.HLE/Loaders/Compression/Lz4.cs
Normal file
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders.Compression
|
||||
{
|
||||
static class Lz4
|
||||
{
|
||||
public static byte[] Decompress(byte[] Cmp, int DecLength)
|
||||
{
|
||||
byte[] Dec = new byte[DecLength];
|
||||
|
||||
int CmpPos = 0;
|
||||
int DecPos = 0;
|
||||
|
||||
int GetLength(int Length)
|
||||
{
|
||||
byte Sum;
|
||||
|
||||
if (Length == 0xf)
|
||||
{
|
||||
do
|
||||
{
|
||||
Length += (Sum = Cmp[CmpPos++]);
|
||||
}
|
||||
while (Sum == 0xff);
|
||||
}
|
||||
|
||||
return Length;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
byte Token = Cmp[CmpPos++];
|
||||
|
||||
int EncCount = (Token >> 0) & 0xf;
|
||||
int LitCount = (Token >> 4) & 0xf;
|
||||
|
||||
//Copy literal chunck
|
||||
LitCount = GetLength(LitCount);
|
||||
|
||||
Buffer.BlockCopy(Cmp, CmpPos, Dec, DecPos, LitCount);
|
||||
|
||||
CmpPos += LitCount;
|
||||
DecPos += LitCount;
|
||||
|
||||
if (CmpPos >= Cmp.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//Copy compressed chunck
|
||||
int Back = Cmp[CmpPos++] << 0 |
|
||||
Cmp[CmpPos++] << 8;
|
||||
|
||||
EncCount = GetLength(EncCount) + 4;
|
||||
|
||||
int EncPos = DecPos - Back;
|
||||
|
||||
if (EncCount <= Back)
|
||||
{
|
||||
Buffer.BlockCopy(Dec, EncPos, Dec, DecPos, EncCount);
|
||||
|
||||
DecPos += EncCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (EncCount-- > 0)
|
||||
{
|
||||
Dec[DecPos++] = Dec[EncPos++];
|
||||
}
|
||||
}
|
||||
}
|
||||
while (CmpPos < Cmp.Length &&
|
||||
DecPos < Dec.Length);
|
||||
|
||||
return Dec;
|
||||
}
|
||||
}
|
||||
}
|
15
Ryujinx.HLE/Loaders/ElfDyn.cs
Normal file
15
Ryujinx.HLE/Loaders/ElfDyn.cs
Normal file
|
@ -0,0 +1,15 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
struct ElfDyn
|
||||
{
|
||||
public ElfDynTag Tag { get; private set; }
|
||||
|
||||
public long Value { get; private set; }
|
||||
|
||||
public ElfDyn(ElfDynTag Tag, long Value)
|
||||
{
|
||||
this.Tag = Tag;
|
||||
this.Value = Value;
|
||||
}
|
||||
}
|
||||
}
|
72
Ryujinx.HLE/Loaders/ElfDynTag.cs
Normal file
72
Ryujinx.HLE/Loaders/ElfDynTag.cs
Normal file
|
@ -0,0 +1,72 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
enum ElfDynTag
|
||||
{
|
||||
DT_NULL = 0,
|
||||
DT_NEEDED = 1,
|
||||
DT_PLTRELSZ = 2,
|
||||
DT_PLTGOT = 3,
|
||||
DT_HASH = 4,
|
||||
DT_STRTAB = 5,
|
||||
DT_SYMTAB = 6,
|
||||
DT_RELA = 7,
|
||||
DT_RELASZ = 8,
|
||||
DT_RELAENT = 9,
|
||||
DT_STRSZ = 10,
|
||||
DT_SYMENT = 11,
|
||||
DT_INIT = 12,
|
||||
DT_FINI = 13,
|
||||
DT_SONAME = 14,
|
||||
DT_RPATH = 15,
|
||||
DT_SYMBOLIC = 16,
|
||||
DT_REL = 17,
|
||||
DT_RELSZ = 18,
|
||||
DT_RELENT = 19,
|
||||
DT_PLTREL = 20,
|
||||
DT_DEBUG = 21,
|
||||
DT_TEXTREL = 22,
|
||||
DT_JMPREL = 23,
|
||||
DT_BIND_NOW = 24,
|
||||
DT_INIT_ARRAY = 25,
|
||||
DT_FINI_ARRAY = 26,
|
||||
DT_INIT_ARRAYSZ = 27,
|
||||
DT_FINI_ARRAYSZ = 28,
|
||||
DT_RUNPATH = 29,
|
||||
DT_FLAGS = 30,
|
||||
DT_ENCODING = 32,
|
||||
DT_PREINIT_ARRAY = 32,
|
||||
DT_PREINIT_ARRAYSZ = 33,
|
||||
DT_GNU_PRELINKED = 0x6ffffdf5,
|
||||
DT_GNU_CONFLICTSZ = 0x6ffffdf6,
|
||||
DT_GNU_LIBLISTSZ = 0x6ffffdf7,
|
||||
DT_CHECKSUM = 0x6ffffdf8,
|
||||
DT_PLTPADSZ = 0x6ffffdf9,
|
||||
DT_MOVEENT = 0x6ffffdfa,
|
||||
DT_MOVESZ = 0x6ffffdfb,
|
||||
DT_FEATURE_1 = 0x6ffffdfc,
|
||||
DT_POSFLAG_1 = 0x6ffffdfd,
|
||||
DT_SYMINSZ = 0x6ffffdfe,
|
||||
DT_SYMINENT = 0x6ffffdff,
|
||||
DT_GNU_HASH = 0x6ffffef5,
|
||||
DT_TLSDESC_PLT = 0x6ffffef6,
|
||||
DT_TLSDESC_GOT = 0x6ffffef7,
|
||||
DT_GNU_CONFLICT = 0x6ffffef8,
|
||||
DT_GNU_LIBLIST = 0x6ffffef9,
|
||||
DT_CONFIG = 0x6ffffefa,
|
||||
DT_DEPAUDIT = 0x6ffffefb,
|
||||
DT_AUDIT = 0x6ffffefc,
|
||||
DT_PLTPAD = 0x6ffffefd,
|
||||
DT_MOVETAB = 0x6ffffefe,
|
||||
DT_SYMINFO = 0x6ffffeff,
|
||||
DT_VERSYM = 0x6ffffff0,
|
||||
DT_RELACOUNT = 0x6ffffff9,
|
||||
DT_RELCOUNT = 0x6ffffffa,
|
||||
DT_FLAGS_1 = 0x6ffffffb,
|
||||
DT_VERDEF = 0x6ffffffc,
|
||||
DT_VERDEFNUM = 0x6ffffffd,
|
||||
DT_VERNEED = 0x6ffffffe,
|
||||
DT_VERNEEDNUM = 0x6fffffff,
|
||||
DT_AUXILIARY = 0x7ffffffd,
|
||||
DT_FILTER = 0x7fffffff
|
||||
}
|
||||
}
|
19
Ryujinx.HLE/Loaders/ElfRel.cs
Normal file
19
Ryujinx.HLE/Loaders/ElfRel.cs
Normal file
|
@ -0,0 +1,19 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
struct ElfRel
|
||||
{
|
||||
public long Offset { get; private set; }
|
||||
public long Addend { get; private set; }
|
||||
|
||||
public ElfSym Symbol { get; private set; }
|
||||
public ElfRelType Type { get; private set; }
|
||||
|
||||
public ElfRel(long Offset, long Addend, ElfSym Symbol, ElfRelType Type)
|
||||
{
|
||||
this.Offset = Offset;
|
||||
this.Addend = Addend;
|
||||
this.Symbol = Symbol;
|
||||
this.Type = Type;
|
||||
}
|
||||
}
|
||||
}
|
128
Ryujinx.HLE/Loaders/ElfRelType.cs
Normal file
128
Ryujinx.HLE/Loaders/ElfRelType.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
enum ElfRelType
|
||||
{
|
||||
R_AARCH64_NONE = 0,
|
||||
R_AARCH64_ABS64 = 257,
|
||||
R_AARCH64_ABS32 = 258,
|
||||
R_AARCH64_ABS16 = 259,
|
||||
R_AARCH64_PREL64 = 260,
|
||||
R_AARCH64_PREL32 = 261,
|
||||
R_AARCH64_PREL16 = 262,
|
||||
R_AARCH64_MOVW_UABS_G0 = 263,
|
||||
R_AARCH64_MOVW_UABS_G0_NC = 264,
|
||||
R_AARCH64_MOVW_UABS_G1 = 265,
|
||||
R_AARCH64_MOVW_UABS_G1_NC = 266,
|
||||
R_AARCH64_MOVW_UABS_G2 = 267,
|
||||
R_AARCH64_MOVW_UABS_G2_NC = 268,
|
||||
R_AARCH64_MOVW_UABS_G3 = 269,
|
||||
R_AARCH64_MOVW_SABS_G0 = 270,
|
||||
R_AARCH64_MOVW_SABS_G1 = 271,
|
||||
R_AARCH64_MOVW_SABS_G2 = 272,
|
||||
R_AARCH64_LD_PREL_LO19 = 273,
|
||||
R_AARCH64_ADR_PREL_LO21 = 274,
|
||||
R_AARCH64_ADR_PREL_PG_HI21 = 275,
|
||||
R_AARCH64_ADR_PREL_PG_HI21_NC = 276,
|
||||
R_AARCH64_ADD_ABS_LO12_NC = 277,
|
||||
R_AARCH64_LDST8_ABS_LO12_NC = 278,
|
||||
R_AARCH64_TSTBR14 = 279,
|
||||
R_AARCH64_CONDBR19 = 280,
|
||||
R_AARCH64_JUMP26 = 282,
|
||||
R_AARCH64_CALL26 = 283,
|
||||
R_AARCH64_LDST16_ABS_LO12_NC = 284,
|
||||
R_AARCH64_LDST32_ABS_LO12_NC = 285,
|
||||
R_AARCH64_LDST64_ABS_LO12_NC = 286,
|
||||
R_AARCH64_MOVW_PREL_G0 = 287,
|
||||
R_AARCH64_MOVW_PREL_G0_NC = 288,
|
||||
R_AARCH64_MOVW_PREL_G1 = 289,
|
||||
R_AARCH64_MOVW_PREL_G1_NC = 290,
|
||||
R_AARCH64_MOVW_PREL_G2 = 291,
|
||||
R_AARCH64_MOVW_PREL_G2_NC = 292,
|
||||
R_AARCH64_MOVW_PREL_G3 = 293,
|
||||
R_AARCH64_LDST128_ABS_LO12_NC = 299,
|
||||
R_AARCH64_MOVW_GOTOFF_G0 = 300,
|
||||
R_AARCH64_MOVW_GOTOFF_G0_NC = 301,
|
||||
R_AARCH64_MOVW_GOTOFF_G1 = 302,
|
||||
R_AARCH64_MOVW_GOTOFF_G1_NC = 303,
|
||||
R_AARCH64_MOVW_GOTOFF_G2 = 304,
|
||||
R_AARCH64_MOVW_GOTOFF_G2_NC = 305,
|
||||
R_AARCH64_MOVW_GOTOFF_G3 = 306,
|
||||
R_AARCH64_GOTREL64 = 307,
|
||||
R_AARCH64_GOTREL32 = 308,
|
||||
R_AARCH64_GOT_LD_PREL19 = 309,
|
||||
R_AARCH64_LD64_GOTOFF_LO15 = 310,
|
||||
R_AARCH64_ADR_GOT_PAGE = 311,
|
||||
R_AARCH64_LD64_GOT_LO12_NC = 312,
|
||||
R_AARCH64_LD64_GOTPAGE_LO15 = 313,
|
||||
R_AARCH64_TLSGD_ADR_PREL21 = 512,
|
||||
R_AARCH64_TLSGD_ADR_PAGE21 = 513,
|
||||
R_AARCH64_TLSGD_ADD_LO12_NC = 514,
|
||||
R_AARCH64_TLSGD_MOVW_G1 = 515,
|
||||
R_AARCH64_TLSGD_MOVW_G0_NC = 516,
|
||||
R_AARCH64_TLSLD_ADR_PREL21 = 517,
|
||||
R_AARCH64_TLSLD_ADR_PAGE21 = 518,
|
||||
R_AARCH64_TLSLD_ADD_LO12_NC = 519,
|
||||
R_AARCH64_TLSLD_MOVW_G1 = 520,
|
||||
R_AARCH64_TLSLD_MOVW_G0_NC = 521,
|
||||
R_AARCH64_TLSLD_LD_PREL19 = 522,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 523,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 524,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 525,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 526,
|
||||
R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 527,
|
||||
R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 528,
|
||||
R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 529,
|
||||
R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 530,
|
||||
R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 531,
|
||||
R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 532,
|
||||
R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 533,
|
||||
R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 534,
|
||||
R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 535,
|
||||
R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 536,
|
||||
R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 537,
|
||||
R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 538,
|
||||
R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 539,
|
||||
R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 540,
|
||||
R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 541,
|
||||
R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 542,
|
||||
R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 543,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G2 = 544,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G1 = 545,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 546,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G0 = 547,
|
||||
R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 548,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_HI12 = 549,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_LO12 = 550,
|
||||
R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 551,
|
||||
R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 552,
|
||||
R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 553,
|
||||
R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 554,
|
||||
R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 555,
|
||||
R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 556,
|
||||
R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 557,
|
||||
R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 558,
|
||||
R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 559,
|
||||
R_AARCH64_TLSDESC_LD_PREL19 = 560,
|
||||
R_AARCH64_TLSDESC_ADR_PREL21 = 561,
|
||||
R_AARCH64_TLSDESC_ADR_PAGE21 = 562,
|
||||
R_AARCH64_TLSDESC_LD64_LO12 = 563,
|
||||
R_AARCH64_TLSDESC_ADD_LO12 = 564,
|
||||
R_AARCH64_TLSDESC_OFF_G1 = 565,
|
||||
R_AARCH64_TLSDESC_OFF_G0_NC = 566,
|
||||
R_AARCH64_TLSDESC_LDR = 567,
|
||||
R_AARCH64_TLSDESC_ADD = 568,
|
||||
R_AARCH64_TLSDESC_CALL = 569,
|
||||
R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 570,
|
||||
R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 571,
|
||||
R_AARCH64_TLSLD_LDST128_DTPREL_LO12 = 572,
|
||||
R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC = 573,
|
||||
R_AARCH64_COPY = 1024,
|
||||
R_AARCH64_GLOB_DAT = 1025,
|
||||
R_AARCH64_JUMP_SLOT = 1026,
|
||||
R_AARCH64_RELATIVE = 1027,
|
||||
R_AARCH64_TLS_DTPMOD64 = 1028,
|
||||
R_AARCH64_TLS_DTPREL64 = 1029,
|
||||
R_AARCH64_TLS_TPREL64 = 1030,
|
||||
R_AARCH64_TLSDESC = 1031
|
||||
}
|
||||
}
|
40
Ryujinx.HLE/Loaders/ElfSym.cs
Normal file
40
Ryujinx.HLE/Loaders/ElfSym.cs
Normal file
|
@ -0,0 +1,40 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
struct ElfSym
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public ElfSymType Type { get; private set; }
|
||||
public ElfSymBinding Binding { get; private set; }
|
||||
public ElfSymVisibility Visibility { get; private set; }
|
||||
|
||||
public bool IsFuncOrObject =>
|
||||
Type == ElfSymType.STT_FUNC ||
|
||||
Type == ElfSymType.STT_OBJECT;
|
||||
|
||||
public bool IsGlobalOrWeak =>
|
||||
Binding == ElfSymBinding.STB_GLOBAL ||
|
||||
Binding == ElfSymBinding.STB_WEAK;
|
||||
|
||||
public int SHIdx { get; private set; }
|
||||
public long Value { get; private set; }
|
||||
public long Size { get; private set; }
|
||||
|
||||
public ElfSym(
|
||||
string Name,
|
||||
int Info,
|
||||
int Other,
|
||||
int SHIdx,
|
||||
long Value,
|
||||
long Size)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.Type = (ElfSymType)(Info & 0xf);
|
||||
this.Binding = (ElfSymBinding)(Info >> 4);
|
||||
this.Visibility = (ElfSymVisibility)Other;
|
||||
this.SHIdx = SHIdx;
|
||||
this.Value = Value;
|
||||
this.Size = Size;
|
||||
}
|
||||
}
|
||||
}
|
9
Ryujinx.HLE/Loaders/ElfSymBinding.cs
Normal file
9
Ryujinx.HLE/Loaders/ElfSymBinding.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
enum ElfSymBinding
|
||||
{
|
||||
STB_LOCAL = 0,
|
||||
STB_GLOBAL = 1,
|
||||
STB_WEAK = 2
|
||||
}
|
||||
}
|
13
Ryujinx.HLE/Loaders/ElfSymType.cs
Normal file
13
Ryujinx.HLE/Loaders/ElfSymType.cs
Normal file
|
@ -0,0 +1,13 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
enum ElfSymType
|
||||
{
|
||||
STT_NOTYPE = 0,
|
||||
STT_OBJECT = 1,
|
||||
STT_FUNC = 2,
|
||||
STT_SECTION = 3,
|
||||
STT_FILE = 4,
|
||||
STT_COMMON = 5,
|
||||
STT_TLS = 6
|
||||
}
|
||||
}
|
10
Ryujinx.HLE/Loaders/ElfSymVisibility.cs
Normal file
10
Ryujinx.HLE/Loaders/ElfSymVisibility.cs
Normal file
|
@ -0,0 +1,10 @@
|
|||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
enum ElfSymVisibility
|
||||
{
|
||||
STV_DEFAULT = 0,
|
||||
STV_INTERNAL = 1,
|
||||
STV_HIDDEN = 2,
|
||||
STV_PROTECTED = 3
|
||||
}
|
||||
}
|
173
Ryujinx.HLE/Loaders/Executable.cs
Normal file
173
Ryujinx.HLE/Loaders/Executable.cs
Normal file
|
@ -0,0 +1,173 @@
|
|||
using ChocolArm64.Memory;
|
||||
using Ryujinx.HLE.Loaders.Executables;
|
||||
using Ryujinx.HLE.OsHle;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders
|
||||
{
|
||||
class Executable
|
||||
{
|
||||
private List<ElfDyn> Dynamic;
|
||||
|
||||
private Dictionary<long, string> m_SymbolTable;
|
||||
|
||||
public IReadOnlyDictionary<long, string> SymbolTable => m_SymbolTable;
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
private AMemory Memory;
|
||||
|
||||
public long ImageBase { get; private set; }
|
||||
public long ImageEnd { get; private set; }
|
||||
|
||||
public Executable(IExecutable Exe, AMemory Memory, long ImageBase)
|
||||
{
|
||||
Dynamic = new List<ElfDyn>();
|
||||
|
||||
m_SymbolTable = new Dictionary<long, string>();
|
||||
|
||||
Name = Exe.Name;
|
||||
|
||||
this.Memory = Memory;
|
||||
this.ImageBase = ImageBase;
|
||||
this.ImageEnd = ImageBase;
|
||||
|
||||
WriteData(ImageBase + Exe.TextOffset, Exe.Text, MemoryType.CodeStatic, AMemoryPerm.RX);
|
||||
WriteData(ImageBase + Exe.ROOffset, Exe.RO, MemoryType.CodeMutable, AMemoryPerm.Read);
|
||||
WriteData(ImageBase + Exe.DataOffset, Exe.Data, MemoryType.CodeMutable, AMemoryPerm.RW);
|
||||
|
||||
if (Exe.Mod0Offset == 0)
|
||||
{
|
||||
int BssOffset = Exe.DataOffset + Exe.Data.Length;
|
||||
int BssSize = Exe.BssSize;
|
||||
|
||||
MapBss(ImageBase + BssOffset, BssSize);
|
||||
|
||||
ImageEnd = ImageBase + BssOffset + BssSize;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
long Mod0Offset = ImageBase + Exe.Mod0Offset;
|
||||
|
||||
int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0);
|
||||
long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset;
|
||||
long BssStartOffset = Memory.ReadInt32(Mod0Offset + 0x8) + Mod0Offset;
|
||||
long BssEndOffset = Memory.ReadInt32(Mod0Offset + 0xc) + Mod0Offset;
|
||||
long EhHdrStartOffset = Memory.ReadInt32(Mod0Offset + 0x10) + Mod0Offset;
|
||||
long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset;
|
||||
long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset;
|
||||
|
||||
MapBss(BssStartOffset, BssEndOffset - BssStartOffset);
|
||||
|
||||
ImageEnd = BssEndOffset;
|
||||
|
||||
while (true)
|
||||
{
|
||||
long TagVal = Memory.ReadInt64(DynamicOffset + 0);
|
||||
long Value = Memory.ReadInt64(DynamicOffset + 8);
|
||||
|
||||
DynamicOffset += 0x10;
|
||||
|
||||
ElfDynTag Tag = (ElfDynTag)TagVal;
|
||||
|
||||
if (Tag == ElfDynTag.DT_NULL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
Dynamic.Add(new ElfDyn(Tag, Value));
|
||||
}
|
||||
|
||||
long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB);
|
||||
long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB);
|
||||
|
||||
long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT);
|
||||
|
||||
while ((ulong)SymTblAddr < (ulong)StrTblAddr)
|
||||
{
|
||||
ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr);
|
||||
|
||||
m_SymbolTable.TryAdd(Sym.Value, Sym.Name);
|
||||
|
||||
SymTblAddr += SymEntSize;
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteData(
|
||||
long Position,
|
||||
byte[] Data,
|
||||
MemoryType Type,
|
||||
AMemoryPerm Perm)
|
||||
{
|
||||
Memory.Manager.Map(Position, Data.Length, (int)Type, AMemoryPerm.Write);
|
||||
|
||||
Memory.WriteBytes(Position, Data);
|
||||
|
||||
Memory.Manager.Reprotect(Position, Data.Length, Perm);
|
||||
}
|
||||
|
||||
private void MapBss(long Position, long Size)
|
||||
{
|
||||
Memory.Manager.Map(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||
}
|
||||
|
||||
private ElfRel GetRelocation(long Position)
|
||||
{
|
||||
long Offset = Memory.ReadInt64(Position + 0);
|
||||
long Info = Memory.ReadInt64(Position + 8);
|
||||
long Addend = Memory.ReadInt64(Position + 16);
|
||||
|
||||
int RelType = (int)(Info >> 0);
|
||||
int SymIdx = (int)(Info >> 32);
|
||||
|
||||
ElfSym Symbol = GetSymbol(SymIdx);
|
||||
|
||||
return new ElfRel(Offset, Addend, Symbol, (ElfRelType)RelType);
|
||||
}
|
||||
|
||||
private ElfSym GetSymbol(int Index)
|
||||
{
|
||||
long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB);
|
||||
long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB);
|
||||
|
||||
long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT);
|
||||
|
||||
long Position = SymTblAddr + Index * SymEntSize;
|
||||
|
||||
return GetSymbol(Position, StrTblAddr);
|
||||
}
|
||||
|
||||
private ElfSym GetSymbol(long Position, long StrTblAddr)
|
||||
{
|
||||
int NameIndex = Memory.ReadInt32(Position + 0);
|
||||
int Info = Memory.ReadByte(Position + 4);
|
||||
int Other = Memory.ReadByte(Position + 5);
|
||||
int SHIdx = Memory.ReadInt16(Position + 6);
|
||||
long Value = Memory.ReadInt64(Position + 8);
|
||||
long Size = Memory.ReadInt64(Position + 16);
|
||||
|
||||
string Name = string.Empty;
|
||||
|
||||
for (int Chr; (Chr = Memory.ReadByte(StrTblAddr + NameIndex++)) != 0;)
|
||||
{
|
||||
Name += (char)Chr;
|
||||
}
|
||||
|
||||
return new ElfSym(Name, Info, Other, SHIdx, Value, Size);
|
||||
}
|
||||
|
||||
private long GetFirstValue(ElfDynTag Tag)
|
||||
{
|
||||
foreach (ElfDyn Entry in Dynamic)
|
||||
{
|
||||
if (Entry.Tag == Tag)
|
||||
{
|
||||
return Entry.Value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
17
Ryujinx.HLE/Loaders/Executables/IExecutable.cs
Normal file
17
Ryujinx.HLE/Loaders/Executables/IExecutable.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
namespace Ryujinx.HLE.Loaders.Executables
|
||||
{
|
||||
public interface IExecutable
|
||||
{
|
||||
string Name { get; }
|
||||
|
||||
byte[] Text { get; }
|
||||
byte[] RO { get; }
|
||||
byte[] Data { get; }
|
||||
|
||||
int Mod0Offset { get; }
|
||||
int TextOffset { get; }
|
||||
int ROOffset { get; }
|
||||
int DataOffset { get; }
|
||||
int BssSize { get; }
|
||||
}
|
||||
}
|
60
Ryujinx.HLE/Loaders/Executables/Nro.cs
Normal file
60
Ryujinx.HLE/Loaders/Executables/Nro.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System.IO;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders.Executables
|
||||
{
|
||||
class Nro : IExecutable
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public byte[] Text { get; private set; }
|
||||
public byte[] RO { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
|
||||
public int Mod0Offset { get; private set; }
|
||||
public int TextOffset { get; private set; }
|
||||
public int ROOffset { get; private set; }
|
||||
public int DataOffset { get; private set; }
|
||||
public int BssSize { get; private set; }
|
||||
|
||||
public Nro(Stream Input, string Name)
|
||||
{
|
||||
this.Name = Name;
|
||||
|
||||
BinaryReader Reader = new BinaryReader(Input);
|
||||
|
||||
Input.Seek(4, SeekOrigin.Begin);
|
||||
|
||||
int Mod0Offset = Reader.ReadInt32();
|
||||
int Padding8 = Reader.ReadInt32();
|
||||
int Paddingc = Reader.ReadInt32();
|
||||
int NroMagic = Reader.ReadInt32();
|
||||
int Unknown14 = Reader.ReadInt32();
|
||||
int FileSize = Reader.ReadInt32();
|
||||
int Unknown1c = Reader.ReadInt32();
|
||||
int TextOffset = Reader.ReadInt32();
|
||||
int TextSize = Reader.ReadInt32();
|
||||
int ROOffset = Reader.ReadInt32();
|
||||
int ROSize = Reader.ReadInt32();
|
||||
int DataOffset = Reader.ReadInt32();
|
||||
int DataSize = Reader.ReadInt32();
|
||||
int BssSize = Reader.ReadInt32();
|
||||
|
||||
this.Mod0Offset = Mod0Offset;
|
||||
this.TextOffset = TextOffset;
|
||||
this.ROOffset = ROOffset;
|
||||
this.DataOffset = DataOffset;
|
||||
this.BssSize = BssSize;
|
||||
|
||||
byte[] Read(long Position, int Size)
|
||||
{
|
||||
Input.Seek(Position, SeekOrigin.Begin);
|
||||
|
||||
return Reader.ReadBytes(Size);
|
||||
}
|
||||
|
||||
Text = Read(TextOffset, TextSize);
|
||||
RO = Read(ROOffset, ROSize);
|
||||
Data = Read(DataOffset, DataSize);
|
||||
}
|
||||
}
|
||||
}
|
121
Ryujinx.HLE/Loaders/Executables/Nso.cs
Normal file
121
Ryujinx.HLE/Loaders/Executables/Nso.cs
Normal file
|
@ -0,0 +1,121 @@
|
|||
using Ryujinx.HLE.Loaders.Compression;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Ryujinx.HLE.Loaders.Executables
|
||||
{
|
||||
class Nso : IExecutable
|
||||
{
|
||||
public string Name { get; private set; }
|
||||
|
||||
public byte[] Text { get; private set; }
|
||||
public byte[] RO { get; private set; }
|
||||
public byte[] Data { get; private set; }
|
||||
|
||||
public int Mod0Offset { get; private set; }
|
||||
public int TextOffset { get; private set; }
|
||||
public int ROOffset { get; private set; }
|
||||
public int DataOffset { get; private set; }
|
||||
public int BssSize { get; private set; }
|
||||
|
||||
[Flags]
|
||||
private enum NsoFlags
|
||||
{
|
||||
IsTextCompressed = 1 << 0,
|
||||
IsROCompressed = 1 << 1,
|
||||
IsDataCompressed = 1 << 2,
|
||||
HasTextHash = 1 << 3,
|
||||
HasROHash = 1 << 4,
|
||||
HasDataHash = 1 << 5
|
||||
}
|
||||
|
||||
public Nso(Stream Input, string Name)
|
||||
{
|
||||
this.Name = Name;
|
||||
|
||||
BinaryReader Reader = new BinaryReader(Input);
|
||||
|
||||
Input.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
int NsoMagic = Reader.ReadInt32();
|
||||
int Version = Reader.ReadInt32();
|
||||
int Reserved = Reader.ReadInt32();
|
||||
int FlagsMsk = Reader.ReadInt32();
|
||||
int TextOffset = Reader.ReadInt32();
|
||||
int TextMemOffset = Reader.ReadInt32();
|
||||
int TextDecSize = Reader.ReadInt32();
|
||||
int ModNameOffset = Reader.ReadInt32();
|
||||
int ROOffset = Reader.ReadInt32();
|
||||
int ROMemOffset = Reader.ReadInt32();
|
||||
int RODecSize = Reader.ReadInt32();
|
||||
int ModNameSize = Reader.ReadInt32();
|
||||
int DataOffset = Reader.ReadInt32();
|
||||
int DataMemOffset = Reader.ReadInt32();
|
||||
int DataDecSize = Reader.ReadInt32();
|
||||
int BssSize = Reader.ReadInt32();
|
||||
|
||||
byte[] BuildId = Reader.ReadBytes(0x20);
|
||||
|
||||
int TextSize = Reader.ReadInt32();
|
||||
int ROSize = Reader.ReadInt32();
|
||||
int DataSize = Reader.ReadInt32();
|
||||
|
||||
Input.Seek(0x24, SeekOrigin.Current);
|
||||
|
||||
int DynStrOffset = Reader.ReadInt32();
|
||||
int DynStrSize = Reader.ReadInt32();
|
||||
int DynSymOffset = Reader.ReadInt32();
|
||||
int DynSymSize = Reader.ReadInt32();
|
||||
|
||||
byte[] TextHash = Reader.ReadBytes(0x20);
|
||||
byte[] ROHash = Reader.ReadBytes(0x20);
|
||||
byte[] DataHash = Reader.ReadBytes(0x20);
|
||||
|
||||
NsoFlags Flags = (NsoFlags)FlagsMsk;
|
||||
|
||||
this.TextOffset = TextMemOffset;
|
||||
this.ROOffset = ROMemOffset;
|
||||
this.DataOffset = DataMemOffset;
|
||||
this.BssSize = BssSize;
|
||||
|
||||
//Text segment
|
||||
Input.Seek(TextOffset, SeekOrigin.Begin);
|
||||
|
||||
Text = Reader.ReadBytes(TextSize);
|
||||
|
||||
if (Flags.HasFlag(NsoFlags.IsTextCompressed) || true)
|
||||
{
|
||||
Text = Lz4.Decompress(Text, TextDecSize);
|
||||
}
|
||||
|
||||
//Read-only data segment
|
||||
Input.Seek(ROOffset, SeekOrigin.Begin);
|
||||
|
||||
RO = Reader.ReadBytes(ROSize);
|
||||
|
||||
if (Flags.HasFlag(NsoFlags.IsROCompressed) || true)
|
||||
{
|
||||
RO = Lz4.Decompress(RO, RODecSize);
|
||||
}
|
||||
|
||||
//Data segment
|
||||
Input.Seek(DataOffset, SeekOrigin.Begin);
|
||||
|
||||
Data = Reader.ReadBytes(DataSize);
|
||||
|
||||
if (Flags.HasFlag(NsoFlags.IsDataCompressed) || true)
|
||||
{
|
||||
Data = Lz4.Decompress(Data, DataDecSize);
|
||||
}
|
||||
|
||||
using (MemoryStream TextMS = new MemoryStream(Text))
|
||||
{
|
||||
BinaryReader TextReader = new BinaryReader(TextMS);
|
||||
|
||||
TextMS.Seek(4, SeekOrigin.Begin);
|
||||
|
||||
Mod0Offset = TextReader.ReadInt32();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue