forked from Mirror/Ryujinx
Support loading NSO/NRO without a MOD0 header, stub some functions, support more ids on SvcGetInfo
This commit is contained in:
parent
2347c44bbf
commit
b99e808791
15 changed files with 153 additions and 41 deletions
|
@ -147,7 +147,7 @@ namespace ChocolArm64.Translation
|
||||||
|
|
||||||
int IntCond = (int)Cond;
|
int IntCond = (int)Cond;
|
||||||
|
|
||||||
if (LastFlagOp == LastCmpOp && BranchOps.ContainsKey(Cond))
|
if (LastCmpOp != null && LastFlagOp == LastCmpOp && BranchOps.ContainsKey(Cond))
|
||||||
{
|
{
|
||||||
Ldloc(Tmp3Index, AIoType.Int, GetIntType(LastCmpOp));
|
Ldloc(Tmp3Index, AIoType.Int, GetIntType(LastCmpOp));
|
||||||
Ldloc(Tmp4Index, AIoType.Int, GetIntType(LastCmpOp));
|
Ldloc(Tmp4Index, AIoType.Int, GetIntType(LastCmpOp));
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace Ryujinx.Loaders
|
||||||
{
|
{
|
||||||
class Executable
|
class Executable
|
||||||
{
|
{
|
||||||
private IElf NsoData;
|
private IExecutable NsoData;
|
||||||
private AMemory Memory;
|
private AMemory Memory;
|
||||||
|
|
||||||
private ElfDyn[] Dynamic;
|
private ElfDyn[] Dynamic;
|
||||||
|
@ -15,23 +15,25 @@ namespace Ryujinx.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 Executable(IElf NsoData, AMemory Memory, long ImageBase)
|
public Executable(IExecutable Exe, AMemory Memory, long ImageBase)
|
||||||
{
|
{
|
||||||
this.NsoData = NsoData;
|
this.NsoData = Exe;
|
||||||
this.Memory = Memory;
|
this.Memory = Memory;
|
||||||
this.ImageBase = ImageBase;
|
this.ImageBase = ImageBase;
|
||||||
this.ImageEnd = ImageBase;
|
this.ImageEnd = ImageBase;
|
||||||
|
|
||||||
WriteData(ImageBase + NsoData.TextOffset, NsoData.Text, MemoryType.CodeStatic, AMemoryPerm.RX);
|
WriteData(ImageBase + Exe.TextOffset, Exe.Text, MemoryType.CodeStatic, AMemoryPerm.RX);
|
||||||
WriteData(ImageBase + NsoData.ROOffset, NsoData.RO, MemoryType.Normal, AMemoryPerm.Read);
|
WriteData(ImageBase + Exe.ROOffset, Exe.RO, MemoryType.Normal, AMemoryPerm.Read);
|
||||||
WriteData(ImageBase + NsoData.DataOffset, NsoData.Data, MemoryType.Normal, AMemoryPerm.RW);
|
WriteData(ImageBase + Exe.DataOffset, Exe.Data, MemoryType.Normal, AMemoryPerm.RW);
|
||||||
|
|
||||||
if (NsoData.Text.Count == 0)
|
if (Exe.Mod0Offset == 0)
|
||||||
{
|
{
|
||||||
|
MapBss(ImageBase + Exe.DataOffset + Exe.Data.Count, Exe.BssSize);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long Mod0Offset = ImageBase + NsoData.Mod0Offset;
|
long Mod0Offset = ImageBase + Exe.Mod0Offset;
|
||||||
|
|
||||||
int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0);
|
int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0);
|
||||||
long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset;
|
long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset;
|
||||||
|
@ -41,9 +43,7 @@ namespace Ryujinx.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;
|
||||||
|
|
||||||
long BssSize = BssEndOffset - BssStartOffset;
|
MapBss(BssStartOffset, BssEndOffset - BssStartOffset);
|
||||||
|
|
||||||
Memory.Manager.MapPhys(BssStartOffset, BssSize, (int)MemoryType.Normal, AMemoryPerm.RW);
|
|
||||||
|
|
||||||
ImageEnd = BssEndOffset;
|
ImageEnd = BssEndOffset;
|
||||||
|
|
||||||
|
@ -83,6 +83,11 @@ namespace Ryujinx.Loaders
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MapBss(long Position, long Size)
|
||||||
|
{
|
||||||
|
Memory.Manager.MapPhys(Position, Size, (int)MemoryType.Normal, AMemoryPerm.RW);
|
||||||
|
}
|
||||||
|
|
||||||
private ElfRel GetRelocation(long Position)
|
private ElfRel GetRelocation(long Position)
|
||||||
{
|
{
|
||||||
long Offset = Memory.ReadInt64(Position + 0);
|
long Offset = Memory.ReadInt64(Position + 0);
|
||||||
|
|
|
@ -2,7 +2,7 @@ using System.Collections.ObjectModel;
|
||||||
|
|
||||||
namespace Ryujinx.Loaders.Executables
|
namespace Ryujinx.Loaders.Executables
|
||||||
{
|
{
|
||||||
interface IElf
|
interface IExecutable
|
||||||
{
|
{
|
||||||
ReadOnlyCollection<byte> Text { get; }
|
ReadOnlyCollection<byte> Text { get; }
|
||||||
ReadOnlyCollection<byte> RO { get; }
|
ReadOnlyCollection<byte> RO { get; }
|
|
@ -4,7 +4,7 @@ using System.IO;
|
||||||
|
|
||||||
namespace Ryujinx.Loaders.Executables
|
namespace Ryujinx.Loaders.Executables
|
||||||
{
|
{
|
||||||
class Nro : IElf
|
class Nro : IExecutable
|
||||||
{
|
{
|
||||||
private byte[] m_Text;
|
private byte[] m_Text;
|
||||||
private byte[] m_RO;
|
private byte[] m_RO;
|
||||||
|
|
|
@ -5,7 +5,7 @@ using System.IO;
|
||||||
|
|
||||||
namespace Ryujinx.Loaders.Executables
|
namespace Ryujinx.Loaders.Executables
|
||||||
{
|
{
|
||||||
class Nso : IElf
|
class Nso : IExecutable
|
||||||
{
|
{
|
||||||
private byte[] m_Text;
|
private byte[] m_Text;
|
||||||
private byte[] m_RO;
|
private byte[] m_RO;
|
||||||
|
|
|
@ -20,6 +20,7 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
{ ( "acc:u0", 100), Service.AccU0InitializeApplicationInfo },
|
{ ( "acc:u0", 100), Service.AccU0InitializeApplicationInfo },
|
||||||
{ ( "acc:u0", 101), Service.AccU0GetBaasAccountManagerForApplication },
|
{ ( "acc:u0", 101), Service.AccU0GetBaasAccountManagerForApplication },
|
||||||
{ ( "apm", 0), Service.ApmOpenSession },
|
{ ( "apm", 0), Service.ApmOpenSession },
|
||||||
|
{ ( "apm:p", 0), Service.ApmOpenSession },
|
||||||
{ ( "appletOE", 0), Service.AppletOpenApplicationProxy },
|
{ ( "appletOE", 0), Service.AppletOpenApplicationProxy },
|
||||||
{ ( "audout:u", 0), Service.AudOutListAudioOuts },
|
{ ( "audout:u", 0), Service.AudOutListAudioOuts },
|
||||||
{ ( "audout:u", 1), Service.AudOutOpenAudioOut },
|
{ ( "audout:u", 1), Service.AudOutOpenAudioOut },
|
||||||
|
@ -27,6 +28,7 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
{ ( "audren:u", 1), Service.AudRenGetAudioRendererWorkBufferSize },
|
{ ( "audren:u", 1), Service.AudRenGetAudioRendererWorkBufferSize },
|
||||||
{ ( "friend:a", 0), Service.FriendCreateFriendService },
|
{ ( "friend:a", 0), Service.FriendCreateFriendService },
|
||||||
{ ( "fsp-srv", 1), Service.FspSrvInitialize },
|
{ ( "fsp-srv", 1), Service.FspSrvInitialize },
|
||||||
|
{ ( "fsp-srv", 18), Service.FspSrvMountSdCard },
|
||||||
{ ( "fsp-srv", 51), Service.FspSrvMountSaveData },
|
{ ( "fsp-srv", 51), Service.FspSrvMountSaveData },
|
||||||
{ ( "fsp-srv", 200), Service.FspSrvOpenDataStorageByCurrentProcess },
|
{ ( "fsp-srv", 200), Service.FspSrvOpenDataStorageByCurrentProcess },
|
||||||
{ ( "fsp-srv", 203), Service.FspSrvOpenRomStorage },
|
{ ( "fsp-srv", 203), Service.FspSrvOpenRomStorage },
|
||||||
|
@ -43,11 +45,13 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
{ ( "nvdrv", 2), Service.NvDrvClose },
|
{ ( "nvdrv", 2), Service.NvDrvClose },
|
||||||
{ ( "nvdrv", 3), Service.NvDrvInitialize },
|
{ ( "nvdrv", 3), Service.NvDrvInitialize },
|
||||||
{ ( "nvdrv", 4), Service.NvDrvQueryEvent },
|
{ ( "nvdrv", 4), Service.NvDrvQueryEvent },
|
||||||
|
{ ( "nvdrv", 8), Service.NvDrvSetClientPid },
|
||||||
{ ( "nvdrv:a", 0), Service.NvDrvOpen },
|
{ ( "nvdrv:a", 0), Service.NvDrvOpen },
|
||||||
{ ( "nvdrv:a", 1), Service.NvDrvIoctl },
|
{ ( "nvdrv:a", 1), Service.NvDrvIoctl },
|
||||||
{ ( "nvdrv:a", 2), Service.NvDrvClose },
|
{ ( "nvdrv:a", 2), Service.NvDrvClose },
|
||||||
{ ( "nvdrv:a", 3), Service.NvDrvInitialize },
|
{ ( "nvdrv:a", 3), Service.NvDrvInitialize },
|
||||||
{ ( "nvdrv:a", 4), Service.NvDrvQueryEvent },
|
{ ( "nvdrv:a", 4), Service.NvDrvQueryEvent },
|
||||||
|
{ ( "nvdrv:a", 8), Service.NvDrvSetClientPid },
|
||||||
{ ( "pctl:a", 0), Service.PctlCreateService },
|
{ ( "pctl:a", 0), Service.PctlCreateService },
|
||||||
{ ( "pl:u", 1), Service.PlGetLoadState },
|
{ ( "pl:u", 1), Service.PlGetLoadState },
|
||||||
{ ( "pl:u", 2), Service.PlGetFontSize },
|
{ ( "pl:u", 2), Service.PlGetFontSize },
|
||||||
|
@ -81,6 +85,7 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
{ (typeof(AmIApplicationFunctions), 1), AmIApplicationFunctions.PopLaunchParameter },
|
{ (typeof(AmIApplicationFunctions), 1), AmIApplicationFunctions.PopLaunchParameter },
|
||||||
{ (typeof(AmIApplicationFunctions), 20), AmIApplicationFunctions.EnsureSaveData },
|
{ (typeof(AmIApplicationFunctions), 20), AmIApplicationFunctions.EnsureSaveData },
|
||||||
{ (typeof(AmIApplicationFunctions), 21), AmIApplicationFunctions.GetDesiredLanguage },
|
{ (typeof(AmIApplicationFunctions), 21), AmIApplicationFunctions.GetDesiredLanguage },
|
||||||
|
{ (typeof(AmIApplicationFunctions), 40), AmIApplicationFunctions.NotifyRunning },
|
||||||
|
|
||||||
//IApplicationProxy
|
//IApplicationProxy
|
||||||
{ (typeof(AmIApplicationProxy), 0), AmIApplicationProxy.GetCommonStateGetter },
|
{ (typeof(AmIApplicationProxy), 0), AmIApplicationProxy.GetCommonStateGetter },
|
||||||
|
@ -103,6 +108,7 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
{ (typeof(AmISelfController), 11), AmISelfController.SetOperationModeChangedNotification },
|
{ (typeof(AmISelfController), 11), AmISelfController.SetOperationModeChangedNotification },
|
||||||
{ (typeof(AmISelfController), 12), AmISelfController.SetPerformanceModeChangedNotification },
|
{ (typeof(AmISelfController), 12), AmISelfController.SetPerformanceModeChangedNotification },
|
||||||
{ (typeof(AmISelfController), 13), AmISelfController.SetFocusHandlingMode },
|
{ (typeof(AmISelfController), 13), AmISelfController.SetFocusHandlingMode },
|
||||||
|
{ (typeof(AmISelfController), 16), AmISelfController.SetOutOfFocusSuspendingEnabled },
|
||||||
|
|
||||||
//IStorage
|
//IStorage
|
||||||
{ (typeof(AmIStorage), 0), AmIStorage.Open },
|
{ (typeof(AmIStorage), 0), AmIStorage.Open },
|
||||||
|
@ -142,14 +148,15 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
{ (typeof(TimeISystemClock), 0), TimeISystemClock.GetCurrentTime },
|
{ (typeof(TimeISystemClock), 0), TimeISystemClock.GetCurrentTime },
|
||||||
|
|
||||||
//IApplicationDisplayService
|
//IApplicationDisplayService
|
||||||
{ (typeof(ViIApplicationDisplayService), 100), ViIApplicationDisplayService.GetRelayService },
|
{ (typeof(ViIApplicationDisplayService), 100), ViIApplicationDisplayService.GetRelayService },
|
||||||
{ (typeof(ViIApplicationDisplayService), 101), ViIApplicationDisplayService.GetSystemDisplayService },
|
{ (typeof(ViIApplicationDisplayService), 101), ViIApplicationDisplayService.GetSystemDisplayService },
|
||||||
{ (typeof(ViIApplicationDisplayService), 102), ViIApplicationDisplayService.GetManagerDisplayService },
|
{ (typeof(ViIApplicationDisplayService), 102), ViIApplicationDisplayService.GetManagerDisplayService },
|
||||||
{ (typeof(ViIApplicationDisplayService), 1010), ViIApplicationDisplayService.OpenDisplay },
|
{ (typeof(ViIApplicationDisplayService), 103), ViIApplicationDisplayService.GetIndirectDisplayTransactionService },
|
||||||
{ (typeof(ViIApplicationDisplayService), 2020), ViIApplicationDisplayService.OpenLayer },
|
{ (typeof(ViIApplicationDisplayService), 1010), ViIApplicationDisplayService.OpenDisplay },
|
||||||
{ (typeof(ViIApplicationDisplayService), 2030), ViIApplicationDisplayService.CreateStrayLayer },
|
{ (typeof(ViIApplicationDisplayService), 2020), ViIApplicationDisplayService.OpenLayer },
|
||||||
{ (typeof(ViIApplicationDisplayService), 2101), ViIApplicationDisplayService.SetLayerScalingMode },
|
{ (typeof(ViIApplicationDisplayService), 2030), ViIApplicationDisplayService.CreateStrayLayer },
|
||||||
{ (typeof(ViIApplicationDisplayService), 5202), ViIApplicationDisplayService.GetDisplayVSyncEvent },
|
{ (typeof(ViIApplicationDisplayService), 2101), ViIApplicationDisplayService.SetLayerScalingMode },
|
||||||
|
{ (typeof(ViIApplicationDisplayService), 5202), ViIApplicationDisplayService.GetDisplayVSyncEvent },
|
||||||
|
|
||||||
//IHOSBinderDriver
|
//IHOSBinderDriver
|
||||||
{ (typeof(ViIHOSBinderDriver), 0), ViIHOSBinderDriver.TransactParcel },
|
{ (typeof(ViIHOSBinderDriver), 0), ViIHOSBinderDriver.TransactParcel },
|
||||||
|
@ -189,6 +196,8 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
|
|
||||||
bool IgnoreNullPR = false;
|
bool IgnoreNullPR = false;
|
||||||
|
|
||||||
|
string DbgServiceName = string.Empty;
|
||||||
|
|
||||||
if (Session is HDomain Dom)
|
if (Session is HDomain Dom)
|
||||||
{
|
{
|
||||||
if (Request.DomCmd == IpcDomCmd.SendMsg)
|
if (Request.DomCmd == IpcDomCmd.SendMsg)
|
||||||
|
@ -200,10 +209,14 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
|
|
||||||
if (Obj is HDomain)
|
if (Obj is HDomain)
|
||||||
{
|
{
|
||||||
|
DbgServiceName = $"{ServiceName} {CmdId}";
|
||||||
|
|
||||||
ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
|
ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
|
||||||
}
|
}
|
||||||
else if (Obj != null)
|
else if (Obj != null)
|
||||||
{
|
{
|
||||||
|
DbgServiceName = $"{ServiceName} {Obj.GetType().Name} {CmdId}";
|
||||||
|
|
||||||
ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
|
ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,10 +238,14 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
{
|
{
|
||||||
object Obj = ((HSessionObj)Session).Obj;
|
object Obj = ((HSessionObj)Session).Obj;
|
||||||
|
|
||||||
|
DbgServiceName = $"{ServiceName} {Obj.GetType().Name} {CmdId}";
|
||||||
|
|
||||||
ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
|
ObjectCmds.TryGetValue((Obj.GetType(), CmdId), out ProcReq);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
DbgServiceName = $"{ServiceName} {CmdId}";
|
||||||
|
|
||||||
ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
|
ServiceCmds.TryGetValue((ServiceName, CmdId), out ProcReq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +272,7 @@ namespace Ryujinx.OsHle.Ipc
|
||||||
}
|
}
|
||||||
else if (!IgnoreNullPR)
|
else if (!IgnoreNullPR)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException(ServiceName);
|
throw new NotImplementedException(DbgServiceName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Request.Type == IpcMessageType.Control)
|
else if (Request.Type == IpcMessageType.Control)
|
||||||
|
|
|
@ -35,6 +35,13 @@ namespace Ryujinx.OsHle.Objects
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long NotifyRunning(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
Context.ResponseData.Write(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private static byte[] MakeLaunchParams()
|
private static byte[] MakeLaunchParams()
|
||||||
{
|
{
|
||||||
//Size needs to be at least 0x88 bytes otherwise application errors.
|
//Size needs to be at least 0x88 bytes otherwise application errors.
|
||||||
|
|
|
@ -24,5 +24,12 @@ namespace Ryujinx.OsHle.Objects
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long SetOutOfFocusSuspendingEnabled(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
bool Enable = Context.RequestData.ReadByte() != 0 ? true : false;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -31,6 +31,13 @@ namespace Ryujinx.OsHle.Objects
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long GetIndirectDisplayTransactionService(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
MakeObject(Context, new ViIHOSBinderDriver());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static long OpenDisplay(ServiceCtx Context)
|
public static long OpenDisplay(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
string Name = GetDisplayName(Context);
|
string Name = GetDisplayName(Context);
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Ryujinx.OsHle
|
||||||
AMemoryPerm.RW);
|
AMemoryPerm.RW);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadProgram(IElf Program)
|
public void LoadProgram(IExecutable Program)
|
||||||
{
|
{
|
||||||
Executable Executable = new Executable(Program, Memory, ImageBase);
|
Executable Executable = new Executable(Program, Memory, ImageBase);
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ namespace Ryujinx.OsHle
|
||||||
Thread.Registers.SvcCall += SvcHandler.SvcCall;
|
Thread.Registers.SvcCall += SvcHandler.SvcCall;
|
||||||
Thread.Registers.ProcessId = ProcessId;
|
Thread.Registers.ProcessId = ProcessId;
|
||||||
Thread.Registers.ThreadId = Ns.Os.IdGen.GenerateId();
|
Thread.Registers.ThreadId = Ns.Os.IdGen.GenerateId();
|
||||||
Thread.Registers.Tpidr = TlsPageAddr + TlsSlot * TlsSize;
|
Thread.Registers.Tpidr = TlsPageAddr + TlsSlot * TlsSize;
|
||||||
Thread.Registers.X0 = (ulong)ArgsPtr;
|
Thread.Registers.X0 = (ulong)ArgsPtr;
|
||||||
Thread.Registers.X1 = (ulong)Handle;
|
Thread.Registers.X1 = (ulong)Handle;
|
||||||
Thread.Registers.X31 = (ulong)StackTop;
|
Thread.Registers.X31 = (ulong)StackTop;
|
||||||
|
|
|
@ -11,6 +11,13 @@ namespace Ryujinx.OsHle.Services
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long FspSrvMountSdCard(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
MakeObject(Context, new FspSrvIFileSystem(Context.Ns.VFs.GetSdCardPath()));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public static long FspSrvMountSaveData(ServiceCtx Context)
|
public static long FspSrvMountSaveData(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
MakeObject(Context, new FspSrvIFileSystem(Context.Ns.VFs.GetGameSavesPath()));
|
MakeObject(Context, new FspSrvIFileSystem(Context.Ns.VFs.GetGameSavesPath()));
|
||||||
|
|
|
@ -110,6 +110,15 @@ namespace Ryujinx.OsHle.Services
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static long NvDrvSetClientPid(ServiceCtx Context)
|
||||||
|
{
|
||||||
|
long Pid = Context.RequestData.ReadInt64();
|
||||||
|
|
||||||
|
Context.ResponseData.Write(0);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
private static long NvGpuAsIoctlBindChannel(ServiceCtx Context)
|
private static long NvGpuAsIoctlBindChannel(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
long Position = Context.Request.PtrBuff[0].Position;
|
long Position = Context.Request.PtrBuff[0].Position;
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace Ryujinx.OsHle.Svc
|
||||||
Success = 0,
|
Success = 0,
|
||||||
ErrBadHandle = 0xe401,
|
ErrBadHandle = 0xe401,
|
||||||
ErrTimeout = 0xea01,
|
ErrTimeout = 0xea01,
|
||||||
ErrBadIpcReq = 0xf601,
|
ErrBadInfo = 0xf001,
|
||||||
|
ErrBadIpcReq = 0xf601
|
||||||
}
|
}
|
||||||
|
|
||||||
private Switch Ns;
|
private Switch Ns;
|
||||||
|
|
|
@ -133,11 +133,28 @@ namespace Ryujinx.OsHle.Svc
|
||||||
long Handle = (long)Registers.X2;
|
long Handle = (long)Registers.X2;
|
||||||
int InfoId = (int)Registers.X3;
|
int InfoId = (int)Registers.X3;
|
||||||
|
|
||||||
|
//Fail for info not available on older Kernel versions.
|
||||||
|
if (InfoType == 18 ||
|
||||||
|
InfoType == 19)
|
||||||
|
{
|
||||||
|
Registers.X0 = (int)SvcResult.ErrBadInfo;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (InfoType)
|
switch (InfoType)
|
||||||
{
|
{
|
||||||
case 6: Registers.X1 = GetTotalMem(Memory); break;
|
case 2: Registers.X1 = GetMapRegionBaseAddr(); break;
|
||||||
case 7: Registers.X1 = GetUsedMem(Memory); break;
|
case 3: Registers.X1 = GetMapRegionSize(); break;
|
||||||
case 11: Registers.X1 = GetRnd64(); break;
|
case 4: Registers.X1 = GetHeapRegionBaseAddr(); break;
|
||||||
|
case 5: Registers.X1 = GetHeapRegionSize(); break;
|
||||||
|
case 6: Registers.X1 = GetTotalMem(Memory); break;
|
||||||
|
case 7: Registers.X1 = GetUsedMem(Memory); break;
|
||||||
|
case 11: Registers.X1 = GetRnd64(); break;
|
||||||
|
case 12: Registers.X1 = GetAddrSpaceBaseAddr(); break;
|
||||||
|
case 13: Registers.X1 = GetAddrSpaceSize(); break;
|
||||||
|
case 14: Registers.X1 = GetMapRegionBaseAddr(); break;
|
||||||
|
case 15: Registers.X1 = GetMapRegionSize(); break;
|
||||||
|
|
||||||
default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
|
default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
|
||||||
}
|
}
|
||||||
|
@ -159,5 +176,35 @@ namespace Ryujinx.OsHle.Svc
|
||||||
{
|
{
|
||||||
return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ulong GetAddrSpaceBaseAddr()
|
||||||
|
{
|
||||||
|
return 0x08000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong GetAddrSpaceSize()
|
||||||
|
{
|
||||||
|
return AMemoryMgr.AddrSize - GetAddrSpaceBaseAddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong GetMapRegionBaseAddr()
|
||||||
|
{
|
||||||
|
return 0x80000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong GetMapRegionSize()
|
||||||
|
{
|
||||||
|
return 0x40000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong GetHeapRegionBaseAddr()
|
||||||
|
{
|
||||||
|
return GetMapRegionBaseAddr() + GetMapRegionSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ulong GetHeapRegionSize()
|
||||||
|
{
|
||||||
|
return 0x40000000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,8 +5,9 @@ namespace Ryujinx
|
||||||
{
|
{
|
||||||
class VirtualFs : IDisposable
|
class VirtualFs : IDisposable
|
||||||
{
|
{
|
||||||
private const string BasePath = "Fs";
|
private const string BasePath = "Fs";
|
||||||
private const string SavesPath = "Saves";
|
private const string SavesPath = "Saves";
|
||||||
|
private const string SdCardPath = "SdCard";
|
||||||
|
|
||||||
public Stream RomFs { get; private set; }
|
public Stream RomFs { get; private set; }
|
||||||
|
|
||||||
|
@ -15,7 +16,7 @@ namespace Ryujinx
|
||||||
RomFs = new FileStream(FileName, FileMode.Open, FileAccess.Read);
|
RomFs = new FileStream(FileName, FileMode.Open, FileAccess.Read);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string GetFullPath(string BasePath, string FileName)
|
public string GetFullPath(string BasePath, string FileName)
|
||||||
{
|
{
|
||||||
if (FileName.StartsWith('/'))
|
if (FileName.StartsWith('/'))
|
||||||
{
|
{
|
||||||
|
@ -32,19 +33,23 @@ namespace Ryujinx
|
||||||
return FullPath;
|
return FullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string GetGameSavesPath()
|
public string GetSdCardPath() => MakeDirAndGetFullPath(SdCardPath);
|
||||||
{
|
|
||||||
string SavesDir = Path.Combine(GetBasePath(), SavesPath);
|
|
||||||
|
|
||||||
if (!Directory.Exists(SavesDir))
|
public string GetGameSavesPath() => MakeDirAndGetFullPath(SavesPath);
|
||||||
|
|
||||||
|
private string MakeDirAndGetFullPath(string Dir)
|
||||||
|
{
|
||||||
|
string FullPath = Path.Combine(GetBasePath(), Dir);
|
||||||
|
|
||||||
|
if (!Directory.Exists(FullPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(SavesDir);
|
Directory.CreateDirectory(FullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SavesDir;
|
return FullPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string GetBasePath()
|
public string GetBasePath()
|
||||||
{
|
{
|
||||||
return Path.Combine(Directory.GetCurrentDirectory(), BasePath);
|
return Path.Combine(Directory.GetCurrentDirectory(), BasePath);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue