mirror of
https://git.743378673.xyz/MeloNX/MeloNX.git
synced 2025-08-03 01:57:11 +02:00
aloha
This commit is contained in:
commit
b7e1d9930d
230 changed files with 17548 additions and 0 deletions
79
Ryujinx/OsHle/Svc/SvcHandler.cs
Normal file
79
Ryujinx/OsHle/Svc/SvcHandler.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private delegate void SvcFunc(Switch Ns, ARegisters Registers, AMemory Memory);
|
||||
|
||||
private Dictionary<int, SvcFunc> SvcFuncs = new Dictionary<int, SvcFunc>()
|
||||
{
|
||||
{ 0x01, SvcSetHeapSize },
|
||||
{ 0x03, SvcSetMemoryAttribute },
|
||||
{ 0x04, SvcMapMemory },
|
||||
{ 0x06, SvcQueryMemory },
|
||||
{ 0x08, SvcCreateThread },
|
||||
{ 0x09, SvcStartThread },
|
||||
{ 0x0b, SvcSleepThread },
|
||||
{ 0x0c, SvcGetThreadPriority },
|
||||
{ 0x13, SvcMapSharedMemory },
|
||||
{ 0x14, SvcUnmapSharedMemory },
|
||||
{ 0x15, SvcCreateTransferMemory },
|
||||
{ 0x16, SvcCloseHandle },
|
||||
{ 0x17, SvcResetSignal },
|
||||
{ 0x18, SvcWaitSynchronization },
|
||||
{ 0x1a, SvcArbitrateLock },
|
||||
{ 0x1b, SvcArbitrateUnlock },
|
||||
{ 0x1c, SvcWaitProcessWideKeyAtomic },
|
||||
{ 0x1d, SvcSignalProcessWideKey },
|
||||
{ 0x1e, SvcGetSystemTick },
|
||||
{ 0x1f, SvcConnectToNamedPort },
|
||||
{ 0x21, SvcSendSyncRequest },
|
||||
{ 0x22, SvcSendSyncRequestWithUserBuffer },
|
||||
{ 0x26, SvcBreak },
|
||||
{ 0x27, SvcOutputDebugString },
|
||||
{ 0x29, SvcGetInfo }
|
||||
};
|
||||
|
||||
enum SvcResult
|
||||
{
|
||||
Success = 0,
|
||||
ErrBadHandle = 0xe401,
|
||||
ErrTimeout = 0xea01,
|
||||
ErrBadIpcReq = 0xf601,
|
||||
}
|
||||
|
||||
private Switch Ns;
|
||||
private AMemory Memory;
|
||||
|
||||
private static Random Rng;
|
||||
|
||||
public SvcHandler(Switch Ns, AMemory Memory)
|
||||
{
|
||||
this.Ns = Ns;
|
||||
this.Memory = Memory;
|
||||
}
|
||||
|
||||
static SvcHandler()
|
||||
{
|
||||
Rng = new Random();
|
||||
}
|
||||
|
||||
public void SvcCall(object sender, SvcEventArgs e)
|
||||
{
|
||||
ARegisters Registers = (ARegisters)sender;
|
||||
|
||||
if (SvcFuncs.TryGetValue(e.Id, out SvcFunc Func))
|
||||
{
|
||||
Func(Ns, Registers, Memory);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException(e.Id.ToString("x3"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
126
Ryujinx/OsHle/Svc/SvcMemory.cs
Normal file
126
Ryujinx/OsHle/Svc/SvcMemory.cs
Normal file
|
@ -0,0 +1,126 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using Ryujinx.OsHle.Handles;
|
||||
|
||||
namespace Ryujinx.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private static void SvcSetHeapSize(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int Size = (int)Registers.X1;
|
||||
|
||||
Memory.Manager.SetHeapSize(Size, (int)MemoryType.Heap);
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
Registers.X1 = (ulong)Memory.Manager.HeapAddr;
|
||||
}
|
||||
|
||||
private static void SvcSetMemoryAttribute(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long Position = (long)Registers.X0;
|
||||
long Size = (long)Registers.X1;
|
||||
int State0 = (int)Registers.X2;
|
||||
int State1 = (int)Registers.X3;
|
||||
|
||||
//TODO
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcMapMemory(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long Src = (long)Registers.X0;
|
||||
long Dst = (long)Registers.X1;
|
||||
long Size = (long)Registers.X2;
|
||||
|
||||
Memory.Manager.MapMirror(Src, Dst, Size, (int)MemoryType.MappedMemory);
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcQueryMemory(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long InfoPtr = (long)Registers.X0;
|
||||
long Position = (long)Registers.X2;
|
||||
|
||||
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
|
||||
|
||||
MemoryInfo Info = new MemoryInfo(MapInfo);
|
||||
|
||||
Memory.WriteInt64(InfoPtr + 0x00, Info.BaseAddress);
|
||||
Memory.WriteInt64(InfoPtr + 0x08, Info.Size);
|
||||
Memory.WriteInt32(InfoPtr + 0x10, Info.MemType);
|
||||
Memory.WriteInt32(InfoPtr + 0x14, Info.MemAttr);
|
||||
Memory.WriteInt32(InfoPtr + 0x18, Info.MemPerm);
|
||||
Memory.WriteInt32(InfoPtr + 0x1c, Info.IpcRefCount);
|
||||
Memory.WriteInt32(InfoPtr + 0x20, Info.DeviceRefCount);
|
||||
Memory.WriteInt32(InfoPtr + 0x24, Info.Padding);
|
||||
|
||||
//TODO: X1.
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
Registers.X1 = 0;
|
||||
}
|
||||
|
||||
private static void SvcMapSharedMemory(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int Handle = (int)Registers.X0;
|
||||
long Position = (long)Registers.X1;
|
||||
long Size = (long)Registers.X2;
|
||||
int Perm = (int)Registers.X3;
|
||||
|
||||
HSharedMem HndData = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
||||
|
||||
if (HndData != null)
|
||||
{
|
||||
long Src = Position;
|
||||
long Dst = HndData.PhysPos;
|
||||
|
||||
if (Memory.Manager.MapPhys(Src, Dst, Size,
|
||||
(int)MemoryType.SharedMemory, (AMemoryPerm)Perm))
|
||||
{
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private static void SvcUnmapSharedMemory(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int Handle = (int)Registers.X0;
|
||||
long Position = (long)Registers.X1;
|
||||
long Size = (long)Registers.X2;
|
||||
|
||||
HSharedMem HndData = Ns.Os.Handles.GetData<HSharedMem>(Handle);
|
||||
|
||||
if (HndData != null)
|
||||
{
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private static void SvcCreateTransferMemory(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long Position = (long)Registers.X1;
|
||||
long Size = (long)Registers.X2;
|
||||
int Perm = (int)Registers.X3;
|
||||
|
||||
AMemoryMapInfo MapInfo = Memory.Manager.GetMapInfo(Position);
|
||||
|
||||
Memory.Manager.Reprotect(Position, Size, (AMemoryPerm)Perm);
|
||||
|
||||
long PhysPos = Memory.Manager.GetPhys(Position, AMemoryPerm.None);
|
||||
|
||||
HTransferMem HndData = new HTransferMem(Memory, MapInfo.Perm, Position, Size, PhysPos);
|
||||
|
||||
int Handle = Ns.Os.Handles.GenerateId(HndData);
|
||||
|
||||
Registers.X1 = (ulong)Handle;
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
163
Ryujinx/OsHle/Svc/SvcSystem.cs
Normal file
163
Ryujinx/OsHle/Svc/SvcSystem.cs
Normal file
|
@ -0,0 +1,163 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using Ryujinx.OsHle.Handles;
|
||||
using Ryujinx.OsHle.Ipc;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private static void SvcCloseHandle(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int Handle = (int)Registers.X0;
|
||||
|
||||
Ns.Os.CloseHandle(Handle);
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcResetSignal(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int Handle = (int)Registers.X0;
|
||||
|
||||
//TODO: Implement events.
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcWaitSynchronization(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long HandlesPtr = (long)Registers.X0;
|
||||
int HandlesCount = (int)Registers.X2;
|
||||
long Timeout = (long)Registers.X3;
|
||||
|
||||
//TODO: Implement events.
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcGetSystemTick(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
Registers.X0 = (ulong)Registers.GetSystemReg(3, 3, 14, 0, 1);
|
||||
}
|
||||
|
||||
private static void SvcConnectToNamedPort(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long StackPtr = (long)Registers.X0;
|
||||
long NamePtr = (long)Registers.X1;
|
||||
|
||||
string Name = AMemoryHelper.ReadAsciiString(Memory, NamePtr, 8);
|
||||
|
||||
//TODO: Validate that app has perms to access the service, and that the service
|
||||
//actually exists, return error codes otherwise.
|
||||
|
||||
HSession Session = new HSession(Name);
|
||||
|
||||
Registers.X1 = (ulong)Ns.Os.Handles.GenerateId(Session);
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcSendSyncRequest(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
SendSyncRequest(Ns, Registers, Memory, false);
|
||||
}
|
||||
|
||||
private static void SvcSendSyncRequestWithUserBuffer(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
SendSyncRequest(Ns, Registers, Memory, true);
|
||||
}
|
||||
|
||||
private static void SendSyncRequest(Switch Ns, ARegisters Registers, AMemory Memory, bool IsUser)
|
||||
{
|
||||
long CmdPtr = Registers.TlsAddr;
|
||||
long Size = 0x100;
|
||||
int Handle = 0;
|
||||
|
||||
if (IsUser)
|
||||
{
|
||||
CmdPtr = (long)Registers.X0;
|
||||
Size = (long)Registers.X1;
|
||||
Handle = (int)Registers.X2;
|
||||
}
|
||||
else
|
||||
{
|
||||
Handle = (int)Registers.X0;
|
||||
}
|
||||
|
||||
byte[] CmdData = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
|
||||
|
||||
HSession Session = Ns.Os.Handles.GetData<HSession>(Handle);
|
||||
|
||||
IpcMessage Cmd = new IpcMessage(CmdData, CmdPtr, Session is HDomain);
|
||||
|
||||
if (Session != null)
|
||||
{
|
||||
IpcHandler.ProcessRequest(Ns, Memory, Session, Cmd, CmdPtr, Handle);
|
||||
|
||||
byte[] Response = AMemoryHelper.ReadBytes(Memory, CmdPtr, (int)Size);
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
Registers.X0 = (int)SvcResult.ErrBadIpcReq;
|
||||
}
|
||||
}
|
||||
|
||||
private static void SvcBreak(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long Reason = (long)Registers.X0;
|
||||
long Unknown = (long)Registers.X1;
|
||||
long Info = (long)Registers.X2;
|
||||
|
||||
throw new Exception($"SvcBreak: {Reason} {Unknown} {Info}");
|
||||
}
|
||||
|
||||
private static void SvcOutputDebugString(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long Position = (long)Registers.X0;
|
||||
long Size = (long)Registers.X1;
|
||||
|
||||
string Str = AMemoryHelper.ReadAsciiString(Memory, Position, (int)Size);
|
||||
|
||||
Console.WriteLine($"SvcOutputDebugString: {Str}");
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcGetInfo(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long StackPtr = (long)Registers.X0;
|
||||
int InfoType = (int)Registers.X1;
|
||||
long Handle = (long)Registers.X2;
|
||||
int InfoId = (int)Registers.X3;
|
||||
|
||||
switch (InfoType)
|
||||
{
|
||||
case 6: Registers.X1 = GetTotalMem(Memory); break;
|
||||
case 7: Registers.X1 = GetUsedMem(Memory); break;
|
||||
case 11: Registers.X1 = GetRnd64(); break;
|
||||
|
||||
default: throw new NotImplementedException($"SvcGetInfo: {InfoType} {Handle} {InfoId}");
|
||||
}
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static ulong GetTotalMem(AMemory Memory)
|
||||
{
|
||||
return (ulong)Memory.Manager.GetTotalMemorySize();
|
||||
}
|
||||
|
||||
private static ulong GetUsedMem(AMemory Memory)
|
||||
{
|
||||
return (ulong)Memory.Manager.GetUsedMemorySize();
|
||||
}
|
||||
|
||||
private static ulong GetRnd64()
|
||||
{
|
||||
return (ulong)Rng.Next() + ((ulong)Rng.Next() << 32);
|
||||
}
|
||||
}
|
||||
}
|
79
Ryujinx/OsHle/Svc/SvcThread.cs
Normal file
79
Ryujinx/OsHle/Svc/SvcThread.cs
Normal file
|
@ -0,0 +1,79 @@
|
|||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using Ryujinx.OsHle.Handles;
|
||||
using System.Threading;
|
||||
|
||||
namespace Ryujinx.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private static void SvcCreateThread(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long EntryPoint = (long)Registers.X1;
|
||||
long ArgsPtr = (long)Registers.X2;
|
||||
long StackTop = (long)Registers.X3;
|
||||
int Priority = (int)Registers.X4;
|
||||
int ProcessorId = (int)Registers.X5;
|
||||
|
||||
if (Ns.Os.TryGetProcess(Registers.ProcessId, out Process Process))
|
||||
{
|
||||
int Handle = Process.MakeThread(
|
||||
EntryPoint,
|
||||
StackTop,
|
||||
ArgsPtr,
|
||||
Priority,
|
||||
ProcessorId);
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
Registers.X1 = (ulong)Handle;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private static void SvcStartThread(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int Handle = (int)Registers.X0;
|
||||
|
||||
HThread HndData = Ns.Os.Handles.GetData<HThread>(Handle);
|
||||
|
||||
if (HndData != null)
|
||||
{
|
||||
HndData.Thread.Execute();
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
|
||||
private static void SvcSleepThread(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
ulong NanoSecs = Registers.X0;
|
||||
|
||||
if (NanoSecs == 0)
|
||||
{
|
||||
Thread.Yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep((int)(NanoSecs / 1000000));
|
||||
}
|
||||
}
|
||||
|
||||
private static void SvcGetThreadPriority(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int Handle = (int)Registers.X1;
|
||||
|
||||
HThread HndData = Ns.Os.Handles.GetData<HThread>(Handle);
|
||||
|
||||
if (HndData != null)
|
||||
{
|
||||
Registers.X1 = (ulong)HndData.Thread.Priority;
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
//TODO: Error codes.
|
||||
}
|
||||
}
|
||||
}
|
87
Ryujinx/OsHle/Svc/SvcThreadSync.cs
Normal file
87
Ryujinx/OsHle/Svc/SvcThreadSync.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using ChocolArm64;
|
||||
using ChocolArm64.Memory;
|
||||
using ChocolArm64.State;
|
||||
using Ryujinx.OsHle.Handles;
|
||||
|
||||
namespace Ryujinx.OsHle.Svc
|
||||
{
|
||||
partial class SvcHandler
|
||||
{
|
||||
private static void SvcArbitrateLock(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
int OwnerThreadHandle = (int)Registers.X0;
|
||||
long MutexAddress = (long)Registers.X1;
|
||||
int RequestingThreadHandle = (int)Registers.X2;
|
||||
|
||||
AThread RequestingThread = Ns.Os.Handles.GetData<HThread>(RequestingThreadHandle).Thread;
|
||||
|
||||
Mutex M = new Mutex(Memory, MutexAddress);
|
||||
|
||||
M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);
|
||||
|
||||
//FIXME
|
||||
//M.WaitForLock(RequestingThread, RequestingThreadHandle);
|
||||
|
||||
Memory.WriteInt32(MutexAddress, 0);
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcArbitrateUnlock(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long MutexAddress = (long)Registers.X0;
|
||||
|
||||
if (Ns.Os.Mutexes.TryGetValue(MutexAddress, out Mutex M))
|
||||
{
|
||||
M.Unlock();
|
||||
}
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcWaitProcessWideKeyAtomic(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long MutexAddress = (long)Registers.X0;
|
||||
long CondVarAddress = (long)Registers.X1;
|
||||
int ThreadHandle = (int)Registers.X2;
|
||||
long Timeout = (long)Registers.X3;
|
||||
|
||||
AThread Thread = Ns.Os.Handles.GetData<HThread>(ThreadHandle).Thread;
|
||||
|
||||
if (Ns.Os.Mutexes.TryGetValue(MutexAddress, out Mutex M))
|
||||
{
|
||||
M.GiveUpLock(ThreadHandle);
|
||||
}
|
||||
|
||||
CondVar Signal = new CondVar(Memory, CondVarAddress, Timeout);
|
||||
|
||||
Signal = Ns.Os.CondVars.GetOrAdd(CondVarAddress, Signal);
|
||||
|
||||
Signal.WaitForSignal(ThreadHandle);
|
||||
|
||||
M = new Mutex(Memory, MutexAddress);
|
||||
|
||||
M = Ns.Os.Mutexes.GetOrAdd(MutexAddress, M);
|
||||
|
||||
//FIXME
|
||||
//M.WaitForLock(Thread, ThreadHandle);
|
||||
|
||||
Memory.WriteInt32(MutexAddress, 0);
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
|
||||
private static void SvcSignalProcessWideKey(Switch Ns, ARegisters Registers, AMemory Memory)
|
||||
{
|
||||
long CondVarAddress = (long)Registers.X0;
|
||||
int Count = (int)Registers.X1;
|
||||
|
||||
if (Ns.Os.CondVars.TryGetValue(CondVarAddress, out CondVar Cv))
|
||||
{
|
||||
Cv.SetSignal(Count);
|
||||
}
|
||||
|
||||
Registers.X0 = (int)SvcResult.Success;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue