aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Core/OsHle/Services
diff options
context:
space:
mode:
authoremmauss <emmausssss@gmail.com>2018-02-20 22:09:23 +0200
committergdkchan <gab.dark.100@gmail.com>2018-02-20 17:09:23 -0300
commit62b827f474f0aa2152dd339fcc7cf31084e16a0b (patch)
tree0e5c55b341aee4db0ccb841a084f253ec5e05657 /Ryujinx.Core/OsHle/Services
parentcb665bb715834526d73c9469d16114b287faaecd (diff)
Split main project into core,graphics and chocolarm4 subproject (#29)
Diffstat (limited to 'Ryujinx.Core/OsHle/Services')
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceAcc.cs33
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceApm.cs16
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs16
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceAud.cs71
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceFriend.cs16
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs49
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceHid.cs56
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceLm.cs12
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs610
-rw-r--r--Ryujinx.Core/OsHle/Services/ServicePctl.cs16
-rw-r--r--Ryujinx.Core/OsHle/Services/ServicePl.cs35
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceSet.cs32
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceSm.cs48
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceTime.cs45
-rw-r--r--Ryujinx.Core/OsHle/Services/ServiceVi.cs18
15 files changed, 1073 insertions, 0 deletions
diff --git a/Ryujinx.Core/OsHle/Services/ServiceAcc.cs b/Ryujinx.Core/OsHle/Services/ServiceAcc.cs
new file mode 100644
index 00000000..f25113e5
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceAcc.cs
@@ -0,0 +1,33 @@
+using Ryujinx.Core.OsHle.Objects.Acc;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long AccU0ListOpenUsers(ServiceCtx Context)
+ {
+ return 0;
+ }
+
+ public static long AccU0GetProfile(ServiceCtx Context)
+ {
+ MakeObject(Context, new IProfile());
+
+ return 0;
+ }
+
+ public static long AccU0InitializeApplicationInfo(ServiceCtx Context)
+ {
+ return 0;
+ }
+
+ public static long AccU0GetBaasAccountManagerForApplication(ServiceCtx Context)
+ {
+ MakeObject(Context, new IManagerForApplication());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceApm.cs b/Ryujinx.Core/OsHle/Services/ServiceApm.cs
new file mode 100644
index 00000000..e1bc0d34
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceApm.cs
@@ -0,0 +1,16 @@
+using Ryujinx.Core.OsHle.Objects.Apm;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long ApmOpenSession(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISession());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs b/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs
new file mode 100644
index 00000000..bbb2484b
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceAppletOE.cs
@@ -0,0 +1,16 @@
+using Ryujinx.Core.OsHle.Objects.Am;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long AppletOpenApplicationProxy(ServiceCtx Context)
+ {
+ MakeObject(Context, new IApplicationProxy());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceAud.cs b/Ryujinx.Core/OsHle/Services/ServiceAud.cs
new file mode 100644
index 00000000..a8ba7dc0
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceAud.cs
@@ -0,0 +1,71 @@
+using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Objects.Aud;
+using System.Text;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long AudOutListAudioOuts(ServiceCtx Context)
+ {
+ long Position = Context.Request.ReceiveBuff[0].Position;
+
+ AMemoryHelper.WriteBytes(Context.Memory, Position, Encoding.ASCII.GetBytes("iface"));
+
+ Context.ResponseData.Write(1);
+
+ return 0;
+ }
+
+ public static long AudOutOpenAudioOut(ServiceCtx Context)
+ {
+ MakeObject(Context, new IAudioOut());
+
+ Context.ResponseData.Write(48000); //Sample Rate
+ Context.ResponseData.Write(2); //Channel Count
+ Context.ResponseData.Write(2); //PCM Format
+ /*
+ 0 - Invalid
+ 1 - INT8
+ 2 - INT16
+ 3 - INT24
+ 4 - INT32
+ 5 - PCM Float
+ 6 - ADPCM
+ */
+ Context.ResponseData.Write(0); //Unknown
+
+ return 0;
+ }
+
+ public static long AudRenOpenAudioRenderer(ServiceCtx Context)
+ {
+ MakeObject(Context, new IAudioRenderer());
+
+ return 0;
+ }
+
+ public static long AudRenGetAudioRendererWorkBufferSize(ServiceCtx Context)
+ {
+ int SampleRate = Context.RequestData.ReadInt32();
+ int Unknown4 = Context.RequestData.ReadInt32();
+ int Unknown8 = Context.RequestData.ReadInt32();
+ int UnknownC = Context.RequestData.ReadInt32();
+ int Unknown10 = Context.RequestData.ReadInt32();
+ int Unknown14 = Context.RequestData.ReadInt32();
+ int Unknown18 = Context.RequestData.ReadInt32();
+ int Unknown1c = Context.RequestData.ReadInt32();
+ int Unknown20 = Context.RequestData.ReadInt32();
+ int Unknown24 = Context.RequestData.ReadInt32();
+ int Unknown28 = Context.RequestData.ReadInt32();
+ int Unknown2c = Context.RequestData.ReadInt32();
+ int Rev1Magic = Context.RequestData.ReadInt32();
+
+ Context.ResponseData.Write(0x400L);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceFriend.cs b/Ryujinx.Core/OsHle/Services/ServiceFriend.cs
new file mode 100644
index 00000000..d1229bd4
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceFriend.cs
@@ -0,0 +1,16 @@
+using Ryujinx.Core.OsHle.Objects.Friend;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long FriendCreateFriendService(ServiceCtx Context)
+ {
+ MakeObject(Context, new IFriendService());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs b/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs
new file mode 100644
index 00000000..3fe41cf0
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceFspSrv.cs
@@ -0,0 +1,49 @@
+using Ryujinx.Core.OsHle.Objects.FspSrv;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long FspSrvInitialize(ServiceCtx Context)
+ {
+ return 0;
+ }
+
+ public static long FspSrvMountSdCard(ServiceCtx Context)
+ {
+ MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetSdCardPath()));
+
+ return 0;
+ }
+
+ public static long FspSrvMountSaveData(ServiceCtx Context)
+ {
+ MakeObject(Context, new IFileSystem(Context.Ns.VFs.GetGameSavesPath()));
+
+ return 0;
+ }
+
+ public static long FspSrvOpenDataStorageByCurrentProcess(ServiceCtx Context)
+ {
+ MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs));
+
+ return 0;
+ }
+
+ public static long FspSrvOpenRomStorage(ServiceCtx Context)
+ {
+ MakeObject(Context, new IStorage(Context.Ns.VFs.RomFs));
+
+ return 0;
+ }
+
+ public static long FspSrvGetGlobalAccessLogMode(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(0);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceHid.cs b/Ryujinx.Core/OsHle/Services/ServiceHid.cs
new file mode 100644
index 00000000..4b2e82ff
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceHid.cs
@@ -0,0 +1,56 @@
+using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.Objects.Hid;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long HidCreateAppletResource(ServiceCtx Context)
+ {
+ HSharedMem HidHndData = Context.Ns.Os.Handles.GetData<HSharedMem>(Context.Ns.Os.HidHandle);
+
+ MakeObject(Context, new IAppletResource(HidHndData));
+
+ return 0;
+ }
+
+ public static long HidActivateTouchScreen(ServiceCtx Context)
+ {
+ long Unknown = Context.RequestData.ReadInt64();
+
+ return 0;
+ }
+
+ public static long HidSetSupportedNpadStyleSet(ServiceCtx Context)
+ {
+ long Unknown0 = Context.RequestData.ReadInt64();
+ long Unknown8 = Context.RequestData.ReadInt64();
+
+ return 0;
+ }
+
+ public static long HidSetSupportedNpadIdType(ServiceCtx Context)
+ {
+ long Unknown = Context.RequestData.ReadInt64();
+
+ return 0;
+ }
+
+ public static long HidActivateNpad(ServiceCtx Context)
+ {
+ long Unknown = Context.RequestData.ReadInt64();
+
+ return 0;
+ }
+
+ public static long HidSetNpadJoyHoldType(ServiceCtx Context)
+ {
+ long Unknown0 = Context.RequestData.ReadInt64();
+ long Unknown8 = Context.RequestData.ReadInt64();
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceLm.cs b/Ryujinx.Core/OsHle/Services/ServiceLm.cs
new file mode 100644
index 00000000..1fdde552
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceLm.cs
@@ -0,0 +1,12 @@
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long LmInitialize(ServiceCtx Context)
+ {
+ Context.Session.Initialize();
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs b/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs
new file mode 100644
index 00000000..6c5fdaed
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceNvDrv.cs
@@ -0,0 +1,610 @@
+using ChocolArm64.Memory;
+using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.Ipc;
+using Ryujinx.Core.OsHle.Utilities;
+using Ryujinx.Graphics.Gpu;
+using System;
+using System.Collections.Generic;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ private delegate long ServiceProcessRequest(ServiceCtx Context);
+
+ private static Dictionary<(string, int), ServiceProcessRequest> IoctlCmds =
+ new Dictionary<(string, int), ServiceProcessRequest>()
+ {
+ { ("/dev/nvhost-as-gpu", 0x4101), NvGpuAsIoctlBindChannel },
+ { ("/dev/nvhost-as-gpu", 0x4102), NvGpuAsIoctlAllocSpace },
+ { ("/dev/nvhost-as-gpu", 0x4106), NvGpuAsIoctlMapBufferEx },
+ { ("/dev/nvhost-as-gpu", 0x4108), NvGpuAsIoctlGetVaRegions },
+ { ("/dev/nvhost-as-gpu", 0x4109), NvGpuAsIoctlInitializeEx },
+ { ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig },
+ { ("/dev/nvhost-ctrl", 0x001d), NvHostIoctlCtrlEventWait },
+ { ("/dev/nvhost-ctrl-gpu", 0x4701), NvGpuIoctlZcullGetCtxSize },
+ { ("/dev/nvhost-ctrl-gpu", 0x4702), NvGpuIoctlZcullGetInfo },
+ { ("/dev/nvhost-ctrl-gpu", 0x4705), NvGpuIoctlGetCharacteristics },
+ { ("/dev/nvhost-ctrl-gpu", 0x4706), NvGpuIoctlGetTpcMasks },
+ { ("/dev/nvhost-ctrl-gpu", 0x4714), NvGpuIoctlZbcGetActiveSlotMask },
+ { ("/dev/nvhost-gpu", 0x4714), NvMapIoctlChannelSetUserData },
+ { ("/dev/nvhost-gpu", 0x4801), NvMapIoctlChannelSetNvMap },
+ { ("/dev/nvhost-gpu", 0x4808), NvMapIoctlChannelSubmitGpFifo },
+ { ("/dev/nvhost-gpu", 0x4809), NvMapIoctlChannelAllocObjCtx },
+ { ("/dev/nvhost-gpu", 0x480b), NvMapIoctlChannelZcullBind },
+ { ("/dev/nvhost-gpu", 0x480c), NvMapIoctlChannelSetErrorNotifier },
+ { ("/dev/nvhost-gpu", 0x480d), NvMapIoctlChannelSetPriority },
+ { ("/dev/nvhost-gpu", 0x481a), NvMapIoctlChannelAllocGpFifoEx2 },
+ { ("/dev/nvmap", 0x0101), NvMapIocCreate },
+ { ("/dev/nvmap", 0x0103), NvMapIocFromId },
+ { ("/dev/nvmap", 0x0104), NvMapIocAlloc },
+ { ("/dev/nvmap", 0x0109), NvMapIocParam },
+ { ("/dev/nvmap", 0x010e), NvMapIocGetId },
+ };
+
+ public static long NvDrvOpen(ServiceCtx Context)
+ {
+ long NamePtr = Context.Request.SendBuff[0].Position;
+
+ string Name = AMemoryHelper.ReadAsciiString(Context.Memory, NamePtr);
+
+ int Fd = Context.Ns.Os.Fds.GenerateId(new FileDesc(Name));
+
+ Context.ResponseData.Write(Fd);
+ Context.ResponseData.Write(0);
+
+ return 0;
+ }
+
+ public static long NvDrvIoctl(ServiceCtx Context)
+ {
+ int Fd = Context.RequestData.ReadInt32();
+ int Cmd = Context.RequestData.ReadInt32() & 0xffff;
+
+ FileDesc FdData = Context.Ns.Os.Fds.GetData<FileDesc>(Fd);
+
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ Context.ResponseData.Write(0);
+
+ if (IoctlCmds.TryGetValue((FdData.Name, Cmd), out ServiceProcessRequest ProcReq))
+ {
+ return ProcReq(Context);
+ }
+ else
+ {
+ throw new NotImplementedException($"{FdData.Name} {Cmd:x4}");
+ }
+ }
+
+ public static long NvDrvClose(ServiceCtx Context)
+ {
+ int Fd = Context.RequestData.ReadInt32();
+
+ Context.Ns.Os.Fds.Delete(Fd);
+
+ Context.ResponseData.Write(0);
+
+ return 0;
+ }
+
+ public static long NvDrvInitialize(ServiceCtx Context)
+ {
+ long TransferMemSize = Context.RequestData.ReadInt64();
+ int TransferMemHandle = Context.Request.HandleDesc.ToCopy[0];
+
+ Context.ResponseData.Write(0);
+
+ return 0;
+ }
+
+ public static long NvDrvQueryEvent(ServiceCtx Context)
+ {
+ int Fd = Context.RequestData.ReadInt32();
+ int EventId = Context.RequestData.ReadInt32();
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(0xcafe);
+
+ Context.ResponseData.Write(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)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ int Fd = Context.Memory.ReadInt32(Position);
+
+ return 0;
+ }
+
+ private static long NvGpuAsIoctlAllocSpace(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ int Pages = Reader.ReadInt32();
+ int PageSize = Reader.ReadInt32();
+ int Flags = Reader.ReadInt32();
+ int Padding = Reader.ReadInt32();
+ long Align = Reader.ReadInt64();
+
+ if ((Flags & 1) != 0)
+ {
+ Align = Context.Ns.Gpu.ReserveMemory(Align, (long)Pages * PageSize, 1);
+ }
+ else
+ {
+ Align = Context.Ns.Gpu.ReserveMemory((long)Pages * PageSize, Align);
+ }
+
+ Context.Memory.WriteInt64(Position + 0x10, Align);
+
+ return 0;
+ }
+
+ private static long NvGpuAsIoctlMapBufferEx(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ int Flags = Reader.ReadInt32();
+ int Kind = Reader.ReadInt32();
+ int Handle = Reader.ReadInt32();
+ int PageSize = Reader.ReadInt32();
+ long BuffAddr = Reader.ReadInt64();
+ long MapSize = Reader.ReadInt64();
+ long Offset = Reader.ReadInt64();
+
+ HNvMap NvMap = Context.Ns.Os.Handles.GetData<HNvMap>(Handle);
+
+ if (NvMap != null)
+ {
+ if ((Flags & 1) != 0)
+ {
+ Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, Offset, NvMap.Size);
+ }
+ else
+ {
+ Offset = Context.Ns.Gpu.MapMemory(NvMap.Address, NvMap.Size);
+ }
+ }
+
+ Context.Memory.WriteInt64(Position + 0x20, Offset);
+
+ return 0;
+ }
+
+ private static long NvGpuAsIoctlGetVaRegions(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+ MemWriter Writer = new MemWriter(Context.Memory, Position);
+
+ long Unused = Reader.ReadInt64();
+ int BuffSize = Reader.ReadInt32();
+ int Padding = Reader.ReadInt32();
+
+ BuffSize = 0x30;
+
+ Writer.WriteInt64(Unused);
+ Writer.WriteInt32(BuffSize);
+ Writer.WriteInt32(Padding);
+
+ Writer.WriteInt64(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt64(0);
+
+ Writer.WriteInt64(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt64(0);
+
+ return 0;
+ }
+
+ private static long NvGpuAsIoctlInitializeEx(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ int BigPageSize = Reader.ReadInt32();
+ int AsFd = Reader.ReadInt32();
+ int Flags = Reader.ReadInt32();
+ int Reserved = Reader.ReadInt32();
+ long Unknown10 = Reader.ReadInt64();
+ long Unknown18 = Reader.ReadInt64();
+ long Unknown20 = Reader.ReadInt64();
+
+ return 0;
+ }
+
+ private static long NvHostIoctlCtrlGetConfig(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+ MemWriter Writer = new MemWriter(Context.Memory, Position + 0x82);
+
+ for (int Index = 0; Index < 0x101; Index++)
+ {
+ Writer.WriteByte(0);
+ }
+
+ return 0;
+ }
+
+ private static long NvHostIoctlCtrlEventWait(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ int SyncPtId = Reader.ReadInt32();
+ int Threshold = Reader.ReadInt32();
+ int Timeout = Reader.ReadInt32();
+ int Value = Reader.ReadInt32();
+
+ Context.Memory.WriteInt32(Position + 0xc, 0xcafe);
+
+ return 0;
+ }
+
+ private static long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ Context.Memory.WriteInt32(Position, 1);
+
+ return 0;
+ }
+
+ private static long NvGpuIoctlZcullGetInfo(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemWriter Writer = new MemWriter(Context.Memory, Position);
+
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+
+ return 0;
+ }
+
+ private static long NvGpuIoctlGetCharacteristics(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+ MemWriter Writer = new MemWriter(Context.Memory, Position);
+
+ //Note: We should just ignore the BuffAddr, because official code
+ //does __memcpy_device from Position + 0x10 to BuffAddr.
+ long BuffSize = Reader.ReadInt64();
+ long BuffAddr = Reader.ReadInt64();
+
+ BuffSize = 0xa0;
+
+ Writer.WriteInt64(BuffSize);
+ Writer.WriteInt64(BuffAddr);
+ Writer.WriteInt32(0x120); //NVGPU_GPU_ARCH_GM200
+ Writer.WriteInt32(0xb); //NVGPU_GPU_IMPL_GM20B
+ Writer.WriteInt32(0xa1);
+ Writer.WriteInt32(1);
+ Writer.WriteInt64(0x40000);
+ Writer.WriteInt64(0);
+ Writer.WriteInt32(2);
+ Writer.WriteInt32(0x20); //NVGPU_GPU_BUS_TYPE_AXI
+ Writer.WriteInt32(0x20000);
+ Writer.WriteInt32(0x20000);
+ Writer.WriteInt32(0x1b);
+ Writer.WriteInt32(0x30000);
+ Writer.WriteInt32(1);
+ Writer.WriteInt32(0x503);
+ Writer.WriteInt32(0x503);
+ Writer.WriteInt32(0x80);
+ Writer.WriteInt32(0x28);
+ Writer.WriteInt32(0);
+ Writer.WriteInt64(0x55);
+ Writer.WriteInt32(0x902d); //FERMI_TWOD_A
+ Writer.WriteInt32(0xb197); //MAXWELL_B
+ Writer.WriteInt32(0xb1c0); //MAXWELL_COMPUTE_B
+ Writer.WriteInt32(0xb06f); //MAXWELL_CHANNEL_GPFIFO_A
+ Writer.WriteInt32(0xa140); //KEPLER_INLINE_TO_MEMORY_B
+ Writer.WriteInt32(0xb0b5); //MAXWELL_DMA_COPY_A
+ Writer.WriteInt32(1);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(2);
+ Writer.WriteInt32(1);
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(1);
+ Writer.WriteInt32(0x21d70);
+ Writer.WriteInt32(0);
+ Writer.WriteByte((byte)'g');
+ Writer.WriteByte((byte)'m');
+ Writer.WriteByte((byte)'2');
+ Writer.WriteByte((byte)'0');
+ Writer.WriteByte((byte)'b');
+ Writer.WriteByte((byte)'\0');
+ Writer.WriteByte((byte)'\0');
+ Writer.WriteByte((byte)'\0');
+ Writer.WriteInt64(0);
+
+ return 0;
+ }
+
+ private static long NvGpuIoctlGetTpcMasks(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ int MaskBuffSize = Reader.ReadInt32();
+ int Reserved = Reader.ReadInt32();
+ long MaskBuffAddr = Reader.ReadInt64();
+ long Unknown = Reader.ReadInt64();
+
+ return 0;
+ }
+
+ private static long NvGpuIoctlZbcGetActiveSlotMask(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ Context.Memory.WriteInt32(Position + 0, 7);
+ Context.Memory.WriteInt32(Position + 4, 1);
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelSetUserData(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelSetNvMap(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ int Fd = Context.Memory.ReadInt32(Position);
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelSubmitGpFifo(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+ MemWriter Writer = new MemWriter(Context.Memory, Position + 0x10);
+
+ long GpFifo = Reader.ReadInt64();
+ int Count = Reader.ReadInt32();
+ int Flags = Reader.ReadInt32();
+ int FenceId = Reader.ReadInt32();
+ int FenceVal = Reader.ReadInt32();
+
+ for (int Index = 0; Index < Count; Index++)
+ {
+ long GpFifoHdr = Reader.ReadInt64();
+
+ long GpuAddr = GpFifoHdr & 0xffffffffff;
+
+ int Size = (int)(GpFifoHdr >> 40) & 0x7ffffc;
+
+ long CpuAddr = Context.Ns.Gpu.GetCpuAddr(GpuAddr);
+
+ if (CpuAddr != -1)
+ {
+ byte[] Data = AMemoryHelper.ReadBytes(Context.Memory, CpuAddr, Size);
+
+ NsGpuPBEntry[] PushBuffer = NsGpuPBEntry.DecodePushBuffer(Data);
+
+ Context.Ns.Gpu.ProcessPushBuffer(PushBuffer, Context.Memory);
+ }
+ }
+
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelAllocObjCtx(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ int ClassNum = Context.Memory.ReadInt32(Position + 0);
+ int Flags = Context.Memory.ReadInt32(Position + 4);
+
+ Context.Memory.WriteInt32(Position + 8, 0);
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelZcullBind(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ long GpuVa = Reader.ReadInt64();
+ int Mode = Reader.ReadInt32();
+ int Padding = Reader.ReadInt32();
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelSetErrorNotifier(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ long Offset = Reader.ReadInt64();
+ long Size = Reader.ReadInt64();
+ int Mem = Reader.ReadInt32();
+ int Padding = Reader.ReadInt32();
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelSetPriority(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ int Priority = Context.Memory.ReadInt32(Position);
+
+ return 0;
+ }
+
+ private static long NvMapIoctlChannelAllocGpFifoEx2(ServiceCtx Context)
+ {
+ long Position = Context.Request.PtrBuff[0].Position;
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+ MemWriter Writer = new MemWriter(Context.Memory, Position + 0xc);
+
+ int Count = Reader.ReadInt32();
+ int Flags = Reader.ReadInt32();
+ int Unknown8 = Reader.ReadInt32();
+ long Fence = Reader.ReadInt64();
+ int Unknown14 = Reader.ReadInt32();
+ int Unknown18 = Reader.ReadInt32();
+
+ Writer.WriteInt32(0);
+ Writer.WriteInt32(0);
+
+ return 0;
+ }
+
+ private static long NvMapIocCreate(ServiceCtx Context)
+ {
+ long Position = Context.Request.GetSendBuffPtr();
+
+ int Size = Context.Memory.ReadInt32(Position);
+
+ int Id = Context.Ns.Os.NvMapIds.GenerateId();
+
+ int Handle = Context.Ns.Os.Handles.GenerateId(new HNvMap(Id, Size));
+
+ Context.Memory.WriteInt32(Position + 4, Handle);
+
+ return 0;
+ }
+
+ private static long NvMapIocFromId(ServiceCtx Context)
+ {
+ long Position = Context.Request.GetSendBuffPtr();
+
+ int Id = Context.Memory.ReadInt32(Position);
+
+ int Handle = -1;
+
+ foreach (KeyValuePair<int, object> KV in Context.Ns.Os.Handles)
+ {
+ if (KV.Value is HNvMap NvMap && NvMap.Id == Id)
+ {
+ Handle = KV.Key;
+
+ break;
+ }
+ }
+
+ Context.Memory.WriteInt32(Position + 4, Handle);
+
+ return 0;
+ }
+
+ private static long NvMapIocAlloc(ServiceCtx Context)
+ {
+ long Position = Context.Request.GetSendBuffPtr();
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ int Handle = Reader.ReadInt32();
+ int HeapMask = Reader.ReadInt32();
+ int Flags = Reader.ReadInt32();
+ int Align = Reader.ReadInt32();
+ byte Kind = (byte)Reader.ReadInt64();
+ long Addr = Reader.ReadInt64();
+
+ HNvMap NvMap = Context.Ns.Os.Handles.GetData<HNvMap>(Handle);
+
+ if (NvMap != null)
+ {
+ NvMap.Address = Addr;
+ NvMap.Align = Align;
+ NvMap.Kind = Kind;
+ }
+
+ Logging.Debug($"NvMapIocAlloc at {NvMap.Address:x16}");
+
+ return 0;
+ }
+
+ private static long NvMapIocParam(ServiceCtx Context)
+ {
+ long Position = Context.Request.GetSendBuffPtr();
+
+ MemReader Reader = new MemReader(Context.Memory, Position);
+
+ int Handle = Reader.ReadInt32();
+ int Param = Reader.ReadInt32();
+
+ HNvMap NvMap = Context.Ns.Os.Handles.GetData<HNvMap>(Handle);
+
+ int Response = 0;
+
+ switch (Param)
+ {
+ case 1: Response = NvMap.Size; break;
+ case 2: Response = NvMap.Align; break;
+ case 4: Response = 0x40000000; break;
+ case 5: Response = NvMap.Kind; break;
+ }
+
+ Context.Memory.WriteInt32(Position + 8, Response);
+
+ return 0;
+ }
+
+ private static long NvMapIocGetId(ServiceCtx Context)
+ {
+ long Position = Context.Request.GetSendBuffPtr();
+
+ int Handle = Context.Memory.ReadInt32(Position + 4);
+
+ HNvMap NvMap = Context.Ns.Os.Handles.GetData<HNvMap>(Handle);
+
+ Context.Memory.WriteInt32(Position, NvMap.Id);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServicePctl.cs b/Ryujinx.Core/OsHle/Services/ServicePctl.cs
new file mode 100644
index 00000000..9c4406bb
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServicePctl.cs
@@ -0,0 +1,16 @@
+using Ryujinx.Core.OsHle.Objects.Am;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long PctlCreateService(ServiceCtx Context)
+ {
+ MakeObject(Context, new IParentalControlService());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServicePl.cs b/Ryujinx.Core/OsHle/Services/ServicePl.cs
new file mode 100644
index 00000000..21e6741c
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServicePl.cs
@@ -0,0 +1,35 @@
+using Ryujinx.Core.OsHle.Ipc;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long PlGetLoadState(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(1); //Loaded
+
+ return 0;
+ }
+
+ public static long PlGetFontSize(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(Horizon.FontSize);
+
+ return 0;
+ }
+
+ public static long PlGetSharedMemoryAddressOffset(ServiceCtx Context)
+ {
+ Context.ResponseData.Write(0);
+
+ return 0;
+ }
+
+ public static long PlGetSharedMemoryNativeHandle(ServiceCtx Context)
+ {
+ Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Context.Ns.Os.FontHandle);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceSet.cs b/Ryujinx.Core/OsHle/Services/ServiceSet.cs
new file mode 100644
index 00000000..83ea5b2c
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceSet.cs
@@ -0,0 +1,32 @@
+using ChocolArm64.Memory;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ private const int LangCodesCount = 13;
+
+ public static long SetGetAvailableLanguageCodes(ServiceCtx Context)
+ {
+ int PtrBuffSize = Context.RequestData.ReadInt32();
+
+ if (Context.Request.RecvListBuff.Count > 0)
+ {
+ long Position = Context.Request.RecvListBuff[0].Position;
+ short Size = Context.Request.RecvListBuff[0].Size;
+
+ //This should return an array of ints with values matching the LanguageCode enum.
+ byte[] Data = new byte[Size];
+
+ Data[0] = 0;
+ Data[1] = 1;
+
+ AMemoryHelper.WriteBytes(Context.Memory, Position, Data);
+ }
+
+ Context.ResponseData.Write(LangCodesCount);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceSm.cs b/Ryujinx.Core/OsHle/Services/ServiceSm.cs
new file mode 100644
index 00000000..58abed24
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceSm.cs
@@ -0,0 +1,48 @@
+using Ryujinx.Core.OsHle.Handles;
+using Ryujinx.Core.OsHle.Ipc;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ private const int SmNotInitialized = 0x415;
+
+ public static long SmInitialize(ServiceCtx Context)
+ {
+ Context.Session.Initialize();
+
+ return 0;
+ }
+
+ public static long SmGetService(ServiceCtx Context)
+ {
+ //Only for kernel version > 3.0.0.
+ if (!Context.Session.IsInitialized)
+ {
+ //return SmNotInitialized;
+ }
+
+ string Name = string.Empty;
+
+ for (int Index = 0; Index < 8 &&
+ Context.RequestData.BaseStream.Position <
+ Context.RequestData.BaseStream.Length; Index++)
+ {
+ byte Chr = Context.RequestData.ReadByte();
+
+ if (Chr >= 0x20 && Chr < 0x7f)
+ {
+ Name += (char)Chr;
+ }
+ }
+
+ HSession Session = new HSession(Name);
+
+ int Handle = Context.Ns.Os.Handles.GenerateId(Session);
+
+ Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
+
+ return 0;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceTime.cs b/Ryujinx.Core/OsHle/Services/ServiceTime.cs
new file mode 100644
index 00000000..a5fddcba
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceTime.cs
@@ -0,0 +1,45 @@
+using Ryujinx.Core.OsHle.Objects.Time;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long TimeGetStandardUserSystemClock(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISystemClock(SystemClockType.User));
+
+ return 0;
+ }
+
+ public static long TimeGetStandardNetworkSystemClock(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISystemClock(SystemClockType.Network));
+
+ return 0;
+ }
+
+ public static long TimeGetStandardSteadyClock(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISteadyClock());
+
+ return 0;
+ }
+
+ public static long TimeGetTimeZoneService(ServiceCtx Context)
+ {
+ MakeObject(Context, new ITimeZoneService());
+
+ return 0;
+ }
+
+ public static long TimeGetStandardLocalSystemClock(ServiceCtx Context)
+ {
+ MakeObject(Context, new ISystemClock(SystemClockType.Local));
+
+ return 0;
+ }
+
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Core/OsHle/Services/ServiceVi.cs b/Ryujinx.Core/OsHle/Services/ServiceVi.cs
new file mode 100644
index 00000000..75cdc31b
--- /dev/null
+++ b/Ryujinx.Core/OsHle/Services/ServiceVi.cs
@@ -0,0 +1,18 @@
+using Ryujinx.Core.OsHle.Objects.Vi;
+
+using static Ryujinx.Core.OsHle.Objects.ObjHelper;
+
+namespace Ryujinx.Core.OsHle.Services
+{
+ static partial class Service
+ {
+ public static long ViGetDisplayService(ServiceCtx Context)
+ {
+ int Unknown = Context.RequestData.ReadInt32();
+
+ MakeObject(Context, new IApplicationDisplayService());
+
+ return 0;
+ }
+ }
+} \ No newline at end of file