forked from Mirror/Ryujinx
Initiale hbmenu.nro support (#32)
* Initiale hbmenu.nro support Implement missing SetScreenShotPermission object. Implement missing IsCurrentProcessBeingDebugged in SVC. Add a Extension variable to Executable. Add basic support of hbmenu.nro. * Homebrew.cs correction
This commit is contained in:
parent
b2f733da78
commit
224211367f
8 changed files with 110 additions and 36 deletions
|
@ -13,6 +13,7 @@ namespace Ryujinx.Core.Loaders
|
||||||
|
|
||||||
public long ImageBase { get; private set; }
|
public long ImageBase { get; private set; }
|
||||||
public long ImageEnd { get; private set; }
|
public long ImageEnd { get; private set; }
|
||||||
|
public Extensions Extension { get; private set; }
|
||||||
|
|
||||||
public Executable(IExecutable Exe, AMemory Memory, long ImageBase)
|
public Executable(IExecutable Exe, AMemory Memory, long ImageBase)
|
||||||
{
|
{
|
||||||
|
@ -46,6 +47,8 @@ namespace Ryujinx.Core.Loaders
|
||||||
long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset;
|
long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset;
|
||||||
long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset;
|
long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset;
|
||||||
|
|
||||||
|
Extension = Exe.Extension;
|
||||||
|
|
||||||
MapBss(BssStartOffset, BssEndOffset - BssStartOffset);
|
MapBss(BssStartOffset, BssEndOffset - BssStartOffset);
|
||||||
|
|
||||||
ImageEnd = BssEndOffset;
|
ImageEnd = BssEndOffset;
|
||||||
|
|
|
@ -2,6 +2,12 @@ using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace Ryujinx.Core.Loaders.Executables
|
namespace Ryujinx.Core.Loaders.Executables
|
||||||
{
|
{
|
||||||
|
public enum Extensions
|
||||||
|
{
|
||||||
|
NRO,
|
||||||
|
NSO
|
||||||
|
}
|
||||||
|
|
||||||
public interface IExecutable
|
public interface IExecutable
|
||||||
{
|
{
|
||||||
ReadOnlyCollection<byte> Text { get; }
|
ReadOnlyCollection<byte> Text { get; }
|
||||||
|
@ -13,5 +19,7 @@ namespace Ryujinx.Core.Loaders.Executables
|
||||||
int ROOffset { get; }
|
int ROOffset { get; }
|
||||||
int DataOffset { get; }
|
int DataOffset { get; }
|
||||||
int BssSize { get; }
|
int BssSize { get; }
|
||||||
|
|
||||||
|
Extensions Extension { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,6 +20,8 @@ namespace Ryujinx.Core.Loaders.Executables
|
||||||
public int DataOffset { get; private set; }
|
public int DataOffset { get; private set; }
|
||||||
public int BssSize { get; private set; }
|
public int BssSize { get; private set; }
|
||||||
|
|
||||||
|
public Extensions Extension { get; private set; }
|
||||||
|
|
||||||
public Nro(Stream Input)
|
public Nro(Stream Input)
|
||||||
{
|
{
|
||||||
BinaryReader Reader = new BinaryReader(Input);
|
BinaryReader Reader = new BinaryReader(Input);
|
||||||
|
@ -47,6 +49,8 @@ namespace Ryujinx.Core.Loaders.Executables
|
||||||
this.DataOffset = DataOffset;
|
this.DataOffset = DataOffset;
|
||||||
this.BssSize = BssSize;
|
this.BssSize = BssSize;
|
||||||
|
|
||||||
|
this.Extension = Extensions.NRO;
|
||||||
|
|
||||||
byte[] Read(long Position, int Size)
|
byte[] Read(long Position, int Size)
|
||||||
{
|
{
|
||||||
Input.Seek(Position, SeekOrigin.Begin);
|
Input.Seek(Position, SeekOrigin.Begin);
|
||||||
|
|
|
@ -21,6 +21,8 @@ namespace Ryujinx.Core.Loaders.Executables
|
||||||
public int DataOffset { get; private set; }
|
public int DataOffset { get; private set; }
|
||||||
public int BssSize { get; private set; }
|
public int BssSize { get; private set; }
|
||||||
|
|
||||||
|
public Extensions Extension { get; private set; }
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
private enum NsoFlags
|
private enum NsoFlags
|
||||||
{
|
{
|
||||||
|
@ -79,6 +81,8 @@ namespace Ryujinx.Core.Loaders.Executables
|
||||||
this.DataOffset = DataMemOffset;
|
this.DataOffset = DataMemOffset;
|
||||||
this.BssSize = BssSize;
|
this.BssSize = BssSize;
|
||||||
|
|
||||||
|
this.Extension = Extensions.NSO;
|
||||||
|
|
||||||
//Text segment
|
//Text segment
|
||||||
Input.Seek(TextOffset, SeekOrigin.Begin);
|
Input.Seek(TextOffset, SeekOrigin.Begin);
|
||||||
|
|
||||||
|
|
34
Ryujinx.Core/OsHle/Homebrew.cs
Normal file
34
Ryujinx.Core/OsHle/Homebrew.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using ChocolArm64.Memory;
|
||||||
|
|
||||||
|
namespace Ryujinx.Core.OsHle
|
||||||
|
{
|
||||||
|
public class Homebrew
|
||||||
|
{
|
||||||
|
//http://switchbrew.org/index.php?title=Homebrew_ABI
|
||||||
|
public Homebrew(AMemory Memory, long Position, long MainThreadHandle)
|
||||||
|
{
|
||||||
|
//(NbrKeys * LoaderConfigEntrySize) + 2 buffers for Key2
|
||||||
|
long Size = (4 * 0x18) + 0x1000;
|
||||||
|
Memory.Manager.MapPhys(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||||
|
|
||||||
|
//MainThreadHandle
|
||||||
|
WriteConfigEntry(Memory, ref Position, 1, 0, MainThreadHandle);
|
||||||
|
//NextLoadPath
|
||||||
|
WriteConfigEntry(Memory, ref Position, 2, 0, Position + Size, Position + Size + 0x200);
|
||||||
|
//AppletType
|
||||||
|
WriteConfigEntry(Memory, ref Position, 7);
|
||||||
|
//EndOfList
|
||||||
|
WriteConfigEntry(Memory, ref Position, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteConfigEntry(AMemory Memory, ref long Position, int Key, int Flags = 0, long Value0 = 0L, long Value1 = 0L)
|
||||||
|
{
|
||||||
|
Memory.WriteInt32(Position + 0x00, Key);
|
||||||
|
Memory.WriteInt32(Position + 0x04, Flags);
|
||||||
|
Memory.WriteInt64(Position + 0x08, Value0);
|
||||||
|
Memory.WriteInt64(Position + 0x10, Value1);
|
||||||
|
|
||||||
|
Position += 0x18;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,6 +13,7 @@ namespace Ryujinx.Core.OsHle.Objects.Am
|
||||||
{
|
{
|
||||||
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
m_Commands = new Dictionary<int, ServiceProcessRequest>()
|
||||||
{
|
{
|
||||||
|
{ 10, SetScreenShotPermission },
|
||||||
{ 11, SetOperationModeChangedNotification },
|
{ 11, SetOperationModeChangedNotification },
|
||||||
{ 12, SetPerformanceModeChangedNotification },
|
{ 12, SetPerformanceModeChangedNotification },
|
||||||
{ 13, SetFocusHandlingMode },
|
{ 13, SetFocusHandlingMode },
|
||||||
|
@ -20,6 +21,13 @@ namespace Ryujinx.Core.OsHle.Objects.Am
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long SetScreenShotPermission(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public long SetOperationModeChangedNotification(ServiceCtx Context)
|
public long SetOperationModeChangedNotification(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
||||||
|
|
|
@ -186,6 +186,13 @@ namespace Ryujinx.Core.OsHle
|
||||||
Thread.ThreadState.X1 = (ulong)Handle;
|
Thread.ThreadState.X1 = (ulong)Handle;
|
||||||
Thread.ThreadState.X31 = (ulong)StackTop;
|
Thread.ThreadState.X31 = (ulong)StackTop;
|
||||||
|
|
||||||
|
if (Executables[0].Extension == Extensions.NRO)
|
||||||
|
{
|
||||||
|
Homebrew Homebrew_ABI = new Homebrew(Memory, Executables[0].ImageEnd, (long)Handle);
|
||||||
|
Thread.ThreadState.X0 = (ulong)Executables[0].ImageEnd;
|
||||||
|
Thread.ThreadState.X1 = 0xFFFFFFFFFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
Thread.WorkFinished += ThreadFinished;
|
Thread.WorkFinished += ThreadFinished;
|
||||||
|
|
||||||
ThreadsByTpidr.TryAdd(Thread.ThreadState.Tpidr, ThreadHnd);
|
ThreadsByTpidr.TryAdd(Thread.ThreadState.Tpidr, ThreadHnd);
|
||||||
|
|
|
@ -161,17 +161,18 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
|
|
||||||
switch (InfoType)
|
switch (InfoType)
|
||||||
{
|
{
|
||||||
case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
case 2: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
||||||
case 3: ThreadState.X1 = GetMapRegionSize(); break;
|
case 3: ThreadState.X1 = GetMapRegionSize(); break;
|
||||||
case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break;
|
case 4: ThreadState.X1 = GetHeapRegionBaseAddr(); break;
|
||||||
case 5: ThreadState.X1 = GetHeapRegionSize(); break;
|
case 5: ThreadState.X1 = GetHeapRegionSize(); break;
|
||||||
case 6: ThreadState.X1 = GetTotalMem(); break;
|
case 6: ThreadState.X1 = GetTotalMem(); break;
|
||||||
case 7: ThreadState.X1 = GetUsedMem(); break;
|
case 7: ThreadState.X1 = GetUsedMem(); break;
|
||||||
case 11: ThreadState.X1 = GetRnd64(); break;
|
case 8: ThreadState.X1 = IsCurrentProcessBeingDebugged(); break;
|
||||||
case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break;
|
case 11: ThreadState.X1 = GetRnd64(); break;
|
||||||
case 13: ThreadState.X1 = GetAddrSpaceSize(); break;
|
case 12: ThreadState.X1 = GetAddrSpaceBaseAddr(); break;
|
||||||
case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
case 13: ThreadState.X1 = GetAddrSpaceSize(); break;
|
||||||
case 15: ThreadState.X1 = GetMapRegionSize(); break;
|
case 14: ThreadState.X1 = GetMapRegionBaseAddr(); break;
|
||||||
|
case 15: ThreadState.X1 = GetMapRegionSize(); break;
|
||||||
|
|
||||||
default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
|
default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
|
||||||
}
|
}
|
||||||
|
@ -179,31 +180,6 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
ThreadState.X0 = (int)SvcResult.Success;
|
ThreadState.X0 = (int)SvcResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ulong GetTotalMem()
|
|
||||||
{
|
|
||||||
return (ulong)Memory.Manager.GetTotalMemorySize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetUsedMem()
|
|
||||||
{
|
|
||||||
return (ulong)Memory.Manager.GetUsedMemorySize();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetRnd64()
|
|
||||||
{
|
|
||||||
return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetAddrSpaceBaseAddr()
|
|
||||||
{
|
|
||||||
return 0x08000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetAddrSpaceSize()
|
|
||||||
{
|
|
||||||
return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong GetMapRegionBaseAddr()
|
private ulong GetMapRegionBaseAddr()
|
||||||
{
|
{
|
||||||
return 0x80000000;
|
return 0x80000000;
|
||||||
|
@ -223,5 +199,35 @@ namespace Ryujinx.Core.OsHle.Svc
|
||||||
{
|
{
|
||||||
return 0x40000000;
|
return 0x40000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ulong GetTotalMem()
|
||||||
|
{
|
||||||
|
return (ulong)Memory.Manager.GetTotalMemorySize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong GetUsedMem()
|
||||||
|
{
|
||||||
|
return (ulong)Memory.Manager.GetUsedMemorySize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong IsCurrentProcessBeingDebugged()
|
||||||
|
{
|
||||||
|
return (ulong)0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong GetRnd64()
|
||||||
|
{
|
||||||
|
return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong GetAddrSpaceBaseAddr()
|
||||||
|
{
|
||||||
|
return 0x08000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ulong GetAddrSpaceSize()
|
||||||
|
{
|
||||||
|
return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue