Update 32 bits syscalls to match 64 bits implementation (#892)

* Implement 32 bits syscalls

Co-authored-by: riperiperi <rhy3756547@hotmail.com>

Implement all 32 bits counterparts of the 64 bits syscalls we currently
have.

* Add FlushProcessDataCache32

* Address jd's comments
This commit is contained in:
Thog 2020-01-19 23:21:53 +01:00 committed by gdkchan
parent 81cca88bcd
commit d0f15cb0b1
6 changed files with 481 additions and 1 deletions

View file

@ -35,6 +35,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ConnectToNamedPort(namePtr, out handle); return ConnectToNamedPort(namePtr, out handle);
} }
public KernelResult ConnectToNamedPort32([R(1)] uint namePtr, [R(1)] out int handle)
{
return ConnectToNamedPort(namePtr, out handle);
}
private KernelResult ConnectToNamedPort(ulong namePtr, out int handle) private KernelResult ConnectToNamedPort(ulong namePtr, out int handle)
{ {
handle = 0; handle = 0;
@ -86,11 +91,21 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle); return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle);
} }
public KernelResult SendSyncRequest32([R(0)] int handle)
{
return SendSyncRequest((ulong)_system.Scheduler.GetCurrentThread().Context.Tpidr, 0x100, handle);
}
public KernelResult SendSyncRequestWithUserBuffer64([R(0)] ulong messagePtr, [R(1)] ulong size, [R(2)] int handle) public KernelResult SendSyncRequestWithUserBuffer64([R(0)] ulong messagePtr, [R(1)] ulong size, [R(2)] int handle)
{ {
return SendSyncRequest(messagePtr, size, handle); return SendSyncRequest(messagePtr, size, handle);
} }
public KernelResult SendSyncRequestWithUserBuffer32([R(0)] uint messagePtr, [R(1)] uint size, [R(2)] int handle)
{
return SendSyncRequest(messagePtr, size, handle);
}
private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle) private KernelResult SendSyncRequest(ulong messagePtr, ulong size, int handle)
{ {
byte[] messageData = _process.CpuMemory.ReadBytes((long)messagePtr, (long)size); byte[] messageData = _process.CpuMemory.ReadBytes((long)messagePtr, (long)size);
@ -176,6 +191,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle); return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle);
} }
public KernelResult CreateSession32(
[R(2)] bool isLight,
[R(3)] uint namePtr,
[R(1)] out int serverSessionHandle,
[R(2)] out int clientSessionHandle)
{
return CreateSession(isLight, namePtr, out serverSessionHandle, out clientSessionHandle);
}
private KernelResult CreateSession( private KernelResult CreateSession(
bool isLight, bool isLight,
ulong namePtr, ulong namePtr,
@ -247,6 +271,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return AcceptSession(portHandle, out sessionHandle); return AcceptSession(portHandle, out sessionHandle);
} }
public KernelResult AcceptSession32([R(1)] int portHandle, [R(1)] out int sessionHandle)
{
return AcceptSession(portHandle, out sessionHandle);
}
private KernelResult AcceptSession(int portHandle, out int sessionHandle) private KernelResult AcceptSession(int portHandle, out int sessionHandle)
{ {
sessionHandle = 0; sessionHandle = 0;
@ -304,6 +333,29 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
[R(3)] int replyTargetHandle, [R(3)] int replyTargetHandle,
[R(4)] long timeout, [R(4)] long timeout,
[R(1)] out int handleIndex) [R(1)] out int handleIndex)
{
return ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex);
}
public KernelResult ReplyAndReceive32(
[R(0)] uint timeoutLow,
[R(1)] ulong handlesPtr,
[R(2)] int handlesCount,
[R(3)] int replyTargetHandle,
[R(4)] uint timeoutHigh,
[R(1)] out int handleIndex)
{
long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32));
return ReplyAndReceive(handlesPtr, handlesCount, replyTargetHandle, timeout, out handleIndex);
}
public KernelResult ReplyAndReceive(
ulong handlesPtr,
int handlesCount,
int replyTargetHandle,
long timeout,
out int handleIndex)
{ {
handleIndex = 0; handleIndex = 0;
@ -394,6 +446,16 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle); return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle);
} }
public KernelResult CreatePort32(
[R(0)] uint namePtr,
[R(2)] int maxSessions,
[R(3)] bool isLight,
[R(1)] out int serverPortHandle,
[R(2)] out int clientPortHandle)
{
return CreatePort(maxSessions, isLight, namePtr, out serverPortHandle, out clientPortHandle);
}
private KernelResult CreatePort( private KernelResult CreatePort(
int maxSessions, int maxSessions,
bool isLight, bool isLight,
@ -434,6 +496,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ManageNamedPort(namePtr, maxSessions, out handle); return ManageNamedPort(namePtr, maxSessions, out handle);
} }
public KernelResult ManageNamedPort32([R(1)] uint namePtr, [R(2)] int maxSessions, [R(1)] out int handle)
{
return ManageNamedPort(namePtr, maxSessions, out handle);
}
private KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle) private KernelResult ManageNamedPort(ulong namePtr, int maxSessions, out int handle)
{ {
handle = 0; handle = 0;
@ -479,6 +546,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ConnectToPort(clientPortHandle, out clientSessionHandle); return ConnectToPort(clientPortHandle, out clientSessionHandle);
} }
public KernelResult ConnectToPort32([R(1)] int clientPortHandle, [R(1)] out int clientSessionHandle)
{
return ConnectToPort(clientPortHandle, out clientSessionHandle);
}
private KernelResult ConnectToPort(int clientPortHandle, out int clientSessionHandle) private KernelResult ConnectToPort(int clientPortHandle, out int clientSessionHandle)
{ {
clientSessionHandle = 0; clientSessionHandle = 0;

View file

@ -11,6 +11,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SetHeapSize(size, out position); return SetHeapSize(size, out position);
} }
public KernelResult SetHeapSize32([R(1)] uint size, [R(1)] out uint position)
{
ulong temporaryPosition;
KernelResult result = SetHeapSize(size, out temporaryPosition);
position = (uint)temporaryPosition;
return result;
}
private KernelResult SetHeapSize(ulong size, out ulong position) private KernelResult SetHeapSize(ulong size, out ulong position)
{ {
if ((size & 0xfffffffe001fffff) != 0) if ((size & 0xfffffffe001fffff) != 0)
@ -32,6 +43,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SetMemoryAttribute(position, size, attributeMask, attributeValue); return SetMemoryAttribute(position, size, attributeMask, attributeValue);
} }
public KernelResult SetMemoryAttribute32(
[R(0)] uint position,
[R(1)] uint size,
[R(2)] MemoryAttribute attributeMask,
[R(3)] MemoryAttribute attributeValue)
{
return SetMemoryAttribute(position, size, attributeMask, attributeValue);
}
private KernelResult SetMemoryAttribute( private KernelResult SetMemoryAttribute(
ulong position, ulong position,
ulong size, ulong size,
@ -70,6 +90,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return MapMemory(dst, src, size); return MapMemory(dst, src, size);
} }
public KernelResult MapMemory32([R(0)] uint dst, [R(1)] uint src, [R(2)] uint size)
{
return MapMemory(dst, src, size);
}
private KernelResult MapMemory(ulong dst, ulong src, ulong size) private KernelResult MapMemory(ulong dst, ulong src, ulong size)
{ {
if (!PageAligned(src | dst)) if (!PageAligned(src | dst))
@ -109,6 +134,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return UnmapMemory(dst, src, size); return UnmapMemory(dst, src, size);
} }
public KernelResult UnmapMemory32([R(0)] uint dst, [R(1)] uint src, [R(2)] uint size)
{
return UnmapMemory(dst, src, size);
}
private KernelResult UnmapMemory(ulong dst, ulong src, ulong size) private KernelResult UnmapMemory(ulong dst, ulong src, ulong size)
{ {
if (!PageAligned(src | dst)) if (!PageAligned(src | dst))
@ -148,6 +178,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return QueryMemory(infoPtr, position, out pageInfo); return QueryMemory(infoPtr, position, out pageInfo);
} }
public KernelResult QueryMemory32([R(0)] uint infoPtr, [R(1)] uint r1, [R(2)] uint position, [R(1)] out uint pageInfo)
{
KernelResult result = QueryMemory(infoPtr, position, out ulong pageInfo64);
pageInfo = (uint)pageInfo64;
return result;
}
private KernelResult QueryMemory(ulong infoPtr, ulong position, out ulong pageInfo) private KernelResult QueryMemory(ulong infoPtr, ulong position, out ulong pageInfo)
{ {
KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position); KMemoryInfo blkInfo = _process.MemoryManager.QueryMemory(position);
@ -171,6 +210,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return MapSharedMemory(handle, address, size, permission); return MapSharedMemory(handle, address, size, permission);
} }
public KernelResult MapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size, [R(3)] MemoryPermission permission)
{
return MapSharedMemory(handle, address, size, permission);
}
private KernelResult MapSharedMemory(int handle, ulong address, ulong size, MemoryPermission permission) private KernelResult MapSharedMemory(int handle, ulong address, ulong size, MemoryPermission permission)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -222,6 +266,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return UnmapSharedMemory(handle, address, size); return UnmapSharedMemory(handle, address, size);
} }
public KernelResult UnmapSharedMemory32([R(0)] int handle, [R(1)] uint address, [R(2)] uint size)
{
return UnmapSharedMemory(handle, address, size);
}
private KernelResult UnmapSharedMemory(int handle, ulong address, ulong size) private KernelResult UnmapSharedMemory(int handle, ulong address, ulong size)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -271,6 +320,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return CreateTransferMemory(address, size, permission, out handle); return CreateTransferMemory(address, size, permission, out handle);
} }
public KernelResult CreateTransferMemory32(
[R(1)] uint address,
[R(2)] uint size,
[R(3)] MemoryPermission permission,
[R(1)] out int handle)
{
return CreateTransferMemory(address, size, permission, out handle);
}
private KernelResult CreateTransferMemory(ulong address, ulong size, MemoryPermission permission, out int handle) private KernelResult CreateTransferMemory(ulong address, ulong size, MemoryPermission permission, out int handle)
{ {
handle = 0; handle = 0;
@ -312,6 +370,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return MapPhysicalMemory(address, size); return MapPhysicalMemory(address, size);
} }
public KernelResult MapPhysicalMemory32([R(0)] uint address, [R(1)] uint size)
{
return MapPhysicalMemory(address, size);
}
private KernelResult MapPhysicalMemory(ulong address, ulong size) private KernelResult MapPhysicalMemory(ulong address, ulong size)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -350,6 +413,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return UnmapPhysicalMemory(address, size); return UnmapPhysicalMemory(address, size);
} }
public KernelResult UnmapPhysicalMemory32([R(0)] uint address, [R(1)] uint size)
{
return UnmapPhysicalMemory(address, size);
}
private KernelResult UnmapPhysicalMemory(ulong address, ulong size) private KernelResult UnmapPhysicalMemory(ulong address, ulong size)
{ {
if (!PageAligned(address)) if (!PageAligned(address))
@ -388,6 +456,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return MapProcessCodeMemory(handle, dst, src, size); return MapProcessCodeMemory(handle, dst, src, size);
} }
public KernelResult MapProcessCodeMemory32([R(0)] int handle, [R(1)] uint srcLow, [R(2)] uint dstLow, [R(3)] uint dstHigh, [R(4)] uint srcHigh, [R(5)] uint sizeLow, [R(6)] uint sizeHigh)
{
ulong src = (srcLow | ((ulong)srcHigh << 32));
ulong dst = (dstLow | ((ulong)dstHigh << 32));
ulong size = (sizeLow | ((ulong)sizeHigh << 32));
return MapProcessCodeMemory(handle, dst, src, size);
}
public KernelResult MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) public KernelResult MapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size)
{ {
if (!PageAligned(dst) || !PageAligned(src)) if (!PageAligned(dst) || !PageAligned(src))
@ -430,6 +507,15 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return UnmapProcessCodeMemory(handle, dst, src, size); return UnmapProcessCodeMemory(handle, dst, src, size);
} }
public KernelResult UnmapProcessCodeMemory32([R(0)] int handle, [R(1)] uint srcLow, [R(2)] uint dstLow, [R(3)] uint dstHigh, [R(4)] uint srcHigh, [R(5)] uint sizeLow, [R(6)] uint sizeHigh)
{
ulong src = (srcLow | ((ulong)srcHigh << 32));
ulong dst = (dstLow | ((ulong)dstHigh << 32));
ulong size = (sizeLow | ((ulong)sizeHigh << 32));
return UnmapProcessCodeMemory(handle, dst, src, size);
}
public KernelResult UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size) public KernelResult UnmapProcessCodeMemory(int handle, ulong dst, ulong src, ulong size)
{ {
if (!PageAligned(dst) || !PageAligned(src)) if (!PageAligned(dst) || !PageAligned(src))
@ -472,6 +558,20 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SetProcessMemoryPermission(handle, src, size, permission); return SetProcessMemoryPermission(handle, src, size, permission);
} }
public KernelResult SetProcessMemoryPermission32(
[R(0)] int handle,
[R(1)] uint sizeLow,
[R(2)] uint srcLow,
[R(3)] uint srcHigh,
[R(4)] uint sizeHigh,
[R(5)] MemoryPermission permission)
{
ulong src = (srcLow | ((ulong)srcHigh << 32));
ulong size = (sizeLow | ((ulong)sizeHigh << 32));
return SetProcessMemoryPermission(handle, src, size, permission);
}
public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, MemoryPermission permission) public KernelResult SetProcessMemoryPermission(int handle, ulong src, ulong size, MemoryPermission permission)
{ {
if (!PageAligned(src)) if (!PageAligned(src))

View file

@ -17,11 +17,21 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
ExitProcess(); ExitProcess();
} }
public void ExitProcess32()
{
ExitProcess();
}
public KernelResult TerminateProcess64([R(0)] int handle) public KernelResult TerminateProcess64([R(0)] int handle)
{ {
return TerminateProcess(handle); return TerminateProcess(handle);
} }
public KernelResult TerminateProcess32([R(0)] int handle)
{
return TerminateProcess(handle);
}
private KernelResult TerminateProcess(int handle) private KernelResult TerminateProcess(int handle)
{ {
KProcess process = _process.HandleTable.GetObject<KProcess>(handle); KProcess process = _process.HandleTable.GetObject<KProcess>(handle);
@ -59,6 +69,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SignalEvent(handle); return SignalEvent(handle);
} }
public KernelResult SignalEvent32([R(0)] int handle)
{
return SignalEvent(handle);
}
private KernelResult SignalEvent(int handle) private KernelResult SignalEvent(int handle)
{ {
KWritableEvent writableEvent = _process.HandleTable.GetObject<KWritableEvent>(handle); KWritableEvent writableEvent = _process.HandleTable.GetObject<KWritableEvent>(handle);
@ -84,6 +99,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ClearEvent(handle); return ClearEvent(handle);
} }
public KernelResult ClearEvent32([R(0)] int handle)
{
return ClearEvent(handle);
}
private KernelResult ClearEvent(int handle) private KernelResult ClearEvent(int handle)
{ {
KernelResult result; KernelResult result;
@ -109,6 +129,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return CloseHandle(handle); return CloseHandle(handle);
} }
public KernelResult CloseHandle32([R(0)] int handle)
{
return CloseHandle(handle);
}
private KernelResult CloseHandle(int handle) private KernelResult CloseHandle(int handle)
{ {
KAutoObject obj = _process.HandleTable.GetObject<KAutoObject>(handle); KAutoObject obj = _process.HandleTable.GetObject<KAutoObject>(handle);
@ -139,6 +164,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ResetSignal(handle); return ResetSignal(handle);
} }
public KernelResult ResetSignal32([R(0)] int handle)
{
return ResetSignal(handle);
}
private KernelResult ResetSignal(int handle) private KernelResult ResetSignal(int handle)
{ {
KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
@ -173,11 +203,29 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _system.Scheduler.GetCurrentThread().Context.CntpctEl0; return _system.Scheduler.GetCurrentThread().Context.CntpctEl0;
} }
public void GetSystemTick32([R(0)] out uint resultLow, [R(1)] out uint resultHigh)
{
ulong result = _system.Scheduler.GetCurrentThread().Context.CntpctEl0;
resultLow = (uint)(result & uint.MaxValue);
resultHigh = (uint)(result >> 32);
}
public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out long pid) public KernelResult GetProcessId64([R(1)] int handle, [R(1)] out long pid)
{ {
return GetProcessId(handle, out pid); return GetProcessId(handle, out pid);
} }
public KernelResult GetProcessId32([R(1)] int handle, [R(1)] out int pidLow, [R(2)] out int pidHigh)
{
KernelResult result = GetProcessId(handle, out long pid);
pidLow = (int)(pid & uint.MaxValue);
pidHigh = (int)(pid >> 32);
return result;
}
private KernelResult GetProcessId(int handle, out long pid) private KernelResult GetProcessId(int handle, out long pid)
{ {
KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
@ -208,6 +256,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Break(reason); Break(reason);
} }
public void Break32([R(0)] uint reason, [R(1)] uint r1, [R(2)] uint info)
{
Break(reason);
}
private void Break(ulong reason) private void Break(ulong reason)
{ {
KThread currentThread = _system.Scheduler.GetCurrentThread(); KThread currentThread = _system.Scheduler.GetCurrentThread();
@ -240,6 +293,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
OutputDebugString(strPtr, size); OutputDebugString(strPtr, size);
} }
public void OutputDebugString32([R(0)] uint strPtr, [R(1)] uint size)
{
OutputDebugString(strPtr, size);
}
private void OutputDebugString(ulong strPtr, ulong size) private void OutputDebugString(ulong strPtr, ulong size)
{ {
string str = MemoryHelper.ReadAsciiString(_process.CpuMemory, (long)strPtr, (long)size); string str = MemoryHelper.ReadAsciiString(_process.CpuMemory, (long)strPtr, (long)size);
@ -252,6 +310,23 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return GetInfo(id, handle, subId, out value); return GetInfo(id, handle, subId, out value);
} }
public KernelResult GetInfo32(
[R(0)] uint subIdLow,
[R(1)] uint id,
[R(2)] int handle,
[R(3)] uint subIdHigh,
[R(1)] out uint valueLow,
[R(2)] out uint valueHigh)
{
long subId = (long)(subIdLow | ((ulong)subIdHigh << 32));
KernelResult result = GetInfo(id, handle, subId, out long value);
valueHigh = (uint)(value >> 32);
valueLow = (uint)(value & uint.MaxValue);
return result;
}
private KernelResult GetInfo(uint id, int handle, long subId, out long value) private KernelResult GetInfo(uint id, int handle, long subId, out long value)
{ {
value = 0; value = 0;
@ -483,6 +558,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return CreateEvent(out wEventHandle, out rEventHandle); return CreateEvent(out wEventHandle, out rEventHandle);
} }
public KernelResult CreateEvent32([R(1)] out int wEventHandle, [R(2)] out int rEventHandle)
{
return CreateEvent(out wEventHandle, out rEventHandle);
}
private KernelResult CreateEvent(out int wEventHandle, out int rEventHandle) private KernelResult CreateEvent(out int wEventHandle, out int rEventHandle)
{ {
KEvent Event = new KEvent(_system); KEvent Event = new KEvent(_system);
@ -511,6 +591,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return GetProcessList(address, maxCount, out count); return GetProcessList(address, maxCount, out count);
} }
public KernelResult GetProcessList32([R(1)] ulong address, [R(2)] int maxCount, [R(1)] out int count)
{
return GetProcessList(address, maxCount, out count);
}
private KernelResult GetProcessList(ulong address, int maxCount, out int count) private KernelResult GetProcessList(ulong address, int maxCount, out int count)
{ {
count = 0; count = 0;
@ -565,6 +650,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return GetSystemInfo(id, handle, subId, out value); return GetSystemInfo(id, handle, subId, out value);
} }
public KernelResult GetSystemInfo32([R(1)] uint subIdLow, [R(2)] uint id, [R(3)] int handle, [R(3)] uint subIdHigh, [R(1)] out int valueLow, [R(2)] out int valueHigh)
{
long subId = (long)(subIdLow | ((ulong)subIdHigh << 32));
KernelResult result = GetSystemInfo(id, handle, subId, out long value);
valueHigh = (int)(value >> 32);
valueLow = (int)(value & uint.MaxValue);
return result;
}
private KernelResult GetSystemInfo(uint id, int handle, long subId, out long value) private KernelResult GetSystemInfo(uint id, int handle, long subId, out long value)
{ {
value = 0; value = 0;
@ -620,5 +717,16 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return KernelResult.Success; return KernelResult.Success;
} }
public KernelResult FlushProcessDataCache32(
[R(0)] uint processHandle,
[R(2)] uint addressLow,
[R(3)] uint addressHigh,
[R(1)] uint sizeLow,
[R(4)] uint sizeHigh)
{
// FIXME: This needs to be implemented as ARMv7 doesn't have any way to do cache maintenance operations on EL0. As we don't support (and don't actually need) to flush the cache, this is stubbed.
return KernelResult.Success;
}
} }
} }

View file

@ -90,7 +90,63 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Dictionary<int, string> svcFuncs32 = new Dictionary<int, string> Dictionary<int, string> svcFuncs32 = new Dictionary<int, string>
{ {
// TODO { 0x01, nameof(SvcHandler.SetHeapSize32) },
{ 0x03, nameof(SvcHandler.SetMemoryAttribute32) },
{ 0x04, nameof(SvcHandler.MapMemory32) },
{ 0x05, nameof(SvcHandler.UnmapMemory32) },
{ 0x06, nameof(SvcHandler.QueryMemory32) },
{ 0x07, nameof(SvcHandler.ExitProcess32) },
{ 0x08, nameof(SvcHandler.CreateThread32) },
{ 0x09, nameof(SvcHandler.StartThread32) },
{ 0x0a, nameof(SvcHandler.ExitThread32) },
{ 0x0b, nameof(SvcHandler.SleepThread32) },
{ 0x0c, nameof(SvcHandler.GetThreadPriority32) },
{ 0x0d, nameof(SvcHandler.SetThreadPriority32) },
{ 0x0e, nameof(SvcHandler.GetThreadCoreMask32) },
{ 0x0f, nameof(SvcHandler.SetThreadCoreMask32) },
{ 0x10, nameof(SvcHandler.GetCurrentProcessorNumber32) },
{ 0x11, nameof(SvcHandler.SignalEvent32) },
{ 0x12, nameof(SvcHandler.ClearEvent32) },
{ 0x13, nameof(SvcHandler.MapSharedMemory32) },
{ 0x14, nameof(SvcHandler.UnmapSharedMemory32) },
{ 0x15, nameof(SvcHandler.CreateTransferMemory32) },
{ 0x16, nameof(SvcHandler.CloseHandle32) },
{ 0x17, nameof(SvcHandler.ResetSignal32) },
{ 0x18, nameof(SvcHandler.WaitSynchronization32) },
{ 0x19, nameof(SvcHandler.CancelSynchronization32) },
{ 0x1a, nameof(SvcHandler.ArbitrateLock32) },
{ 0x1b, nameof(SvcHandler.ArbitrateUnlock32) },
{ 0x1c, nameof(SvcHandler.WaitProcessWideKeyAtomic32) },
{ 0x1d, nameof(SvcHandler.SignalProcessWideKey32) },
{ 0x1e, nameof(SvcHandler.GetSystemTick32) },
{ 0x1f, nameof(SvcHandler.ConnectToNamedPort32) },
{ 0x21, nameof(SvcHandler.SendSyncRequest32) },
{ 0x22, nameof(SvcHandler.SendSyncRequestWithUserBuffer32) },
{ 0x24, nameof(SvcHandler.GetProcessId32) },
{ 0x25, nameof(SvcHandler.GetThreadId32) },
{ 0x26, nameof(SvcHandler.Break32) },
{ 0x27, nameof(SvcHandler.OutputDebugString32) },
{ 0x29, nameof(SvcHandler.GetInfo32) },
{ 0x2c, nameof(SvcHandler.MapPhysicalMemory32) },
{ 0x2d, nameof(SvcHandler.UnmapPhysicalMemory32) },
{ 0x32, nameof(SvcHandler.SetThreadActivity32) },
{ 0x33, nameof(SvcHandler.GetThreadContext332) },
{ 0x34, nameof(SvcHandler.WaitForAddress32) },
{ 0x35, nameof(SvcHandler.SignalToAddress32) },
{ 0x40, nameof(SvcHandler.CreateSession32) },
{ 0x41, nameof(SvcHandler.AcceptSession32) },
{ 0x43, nameof(SvcHandler.ReplyAndReceive32) },
{ 0x45, nameof(SvcHandler.CreateEvent32) },
{ 0x5F, nameof(SvcHandler.FlushProcessDataCache32) },
{ 0x65, nameof(SvcHandler.GetProcessList32) },
{ 0x6f, nameof(SvcHandler.GetSystemInfo32) },
{ 0x70, nameof(SvcHandler.CreatePort32) },
{ 0x71, nameof(SvcHandler.ManageNamedPort32) },
{ 0x72, nameof(SvcHandler.ConnectToPort32) },
{ 0x73, nameof(SvcHandler.SetProcessMemoryPermission32) },
{ 0x77, nameof(SvcHandler.MapProcessCodeMemory32) },
{ 0x78, nameof(SvcHandler.UnmapProcessCodeMemory32) },
{ 0x7B, nameof(SvcHandler.TerminateProcess32) }
}; };
foreach (KeyValuePair<int, string> value in svcFuncs32) foreach (KeyValuePair<int, string> value in svcFuncs32)
@ -320,6 +376,12 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
for (int index = 0; index < locals.Count; index++) for (int index = 0; index < locals.Count; index++)
{ {
(LocalBuilder local, RAttribute attribute) = locals[index]; (LocalBuilder local, RAttribute attribute) = locals[index];
if ((registerInUse & (1u << attribute.Index)) != 0)
{
throw new InvalidSvcException($"Method \"{svcName}\" has conflicting output values at register index \"{attribute.Index}\".");
}
generator.Emit(OpCodes.Ldarg_1); generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Ldc_I4, attribute.Index); generator.Emit(OpCodes.Ldc_I4, attribute.Index);
generator.Emit(OpCodes.Ldloc, local); generator.Emit(OpCodes.Ldloc, local);

View file

@ -19,6 +19,17 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle); return CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle);
} }
public KernelResult CreateThread32(
[R(1)] uint entrypoint,
[R(2)] uint argsPtr,
[R(3)] uint stackTop,
[R(0)] int priority,
[R(4)] int cpuCore,
[R(1)] out int handle)
{
return CreateThread(entrypoint, argsPtr, stackTop, priority, cpuCore, out handle);
}
private KernelResult CreateThread( private KernelResult CreateThread(
ulong entrypoint, ulong entrypoint,
ulong argsPtr, ulong argsPtr,
@ -83,6 +94,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return StartThread(handle); return StartThread(handle);
} }
public KernelResult StartThread32([R(0)] int handle)
{
return StartThread(handle);
}
private KernelResult StartThread(int handle) private KernelResult StartThread(int handle)
{ {
KThread thread = _process.HandleTable.GetKThread(handle); KThread thread = _process.HandleTable.GetKThread(handle);
@ -113,6 +129,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
ExitThread(); ExitThread();
} }
public void ExitThread32()
{
ExitThread();
}
private void ExitThread() private void ExitThread()
{ {
KThread currentThread = _system.Scheduler.GetCurrentThread(); KThread currentThread = _system.Scheduler.GetCurrentThread();
@ -127,6 +148,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
SleepThread(timeout); SleepThread(timeout);
} }
public void SleepThread32([R(0)] uint timeoutLow, [R(1)] uint timeoutHigh)
{
long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32));
SleepThread(timeout);
}
private void SleepThread(long timeout) private void SleepThread(long timeout)
{ {
KThread currentThread = _system.Scheduler.GetCurrentThread(); KThread currentThread = _system.Scheduler.GetCurrentThread();
@ -151,6 +179,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return GetThreadPriority(handle, out priority); return GetThreadPriority(handle, out priority);
} }
public KernelResult GetThreadPriority32([R(1)] int handle, [R(1)] out int priority)
{
return GetThreadPriority(handle, out priority);
}
private KernelResult GetThreadPriority(int handle, out int priority) private KernelResult GetThreadPriority(int handle, out int priority)
{ {
KThread thread = _process.HandleTable.GetKThread(handle); KThread thread = _process.HandleTable.GetKThread(handle);
@ -174,6 +207,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SetThreadPriority(handle, priority); return SetThreadPriority(handle, priority);
} }
public KernelResult SetThreadPriority32([R(0)] int handle, [R(1)] int priority)
{
return SetThreadPriority(handle, priority);
}
public KernelResult SetThreadPriority(int handle, int priority) public KernelResult SetThreadPriority(int handle, int priority)
{ {
// TODO: NPDM check. // TODO: NPDM check.
@ -195,6 +233,16 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return GetThreadCoreMask(handle, out preferredCore, out affinityMask); return GetThreadCoreMask(handle, out preferredCore, out affinityMask);
} }
public KernelResult GetThreadCoreMask32([R(2)] int handle, [R(1)] out int preferredCore, [R(2)] out int affinityMaskLow, [R(3)] out int affinityMaskHigh)
{
KernelResult result = GetThreadCoreMask(handle, out preferredCore, out long affinityMask);
affinityMaskLow = (int)(affinityMask >> 32);
affinityMaskHigh = (int)(affinityMask & uint.MaxValue);
return result;
}
private KernelResult GetThreadCoreMask(int handle, out int preferredCore, out long affinityMask) private KernelResult GetThreadCoreMask(int handle, out int preferredCore, out long affinityMask)
{ {
KThread thread = _process.HandleTable.GetKThread(handle); KThread thread = _process.HandleTable.GetKThread(handle);
@ -220,6 +268,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SetThreadCoreMask(handle, preferredCore, affinityMask); return SetThreadCoreMask(handle, preferredCore, affinityMask);
} }
public KernelResult SetThreadCoreMask32([R(0)] int handle, [R(1)] int preferredCore, [R(2)] uint affinityMaskLow, [R(3)] uint affinityMaskHigh)
{
long affinityMask = (long)(affinityMaskLow | ((ulong)affinityMaskHigh << 32));
return SetThreadCoreMask(handle, preferredCore, affinityMask);
}
private KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask) private KernelResult SetThreadCoreMask(int handle, int preferredCore, long affinityMask)
{ {
KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
@ -271,11 +326,28 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _system.Scheduler.GetCurrentThread().CurrentCore; return _system.Scheduler.GetCurrentThread().CurrentCore;
} }
public int GetCurrentProcessorNumber32()
{
return _system.Scheduler.GetCurrentThread().CurrentCore;
}
public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out long threadUid) public KernelResult GetThreadId64([R(1)] int handle, [R(1)] out long threadUid)
{ {
return GetThreadId(handle, out threadUid); return GetThreadId(handle, out threadUid);
} }
public KernelResult GetThreadId32([R(1)] int handle, [R(1)] out uint threadUidLow, [R(2)] out uint threadUidHigh)
{
long threadUid;
KernelResult result = GetThreadId(handle, out threadUid);
threadUidLow = (uint)(threadUid >> 32);
threadUidHigh = (uint)(threadUid & uint.MaxValue);
return result;
}
private KernelResult GetThreadId(int handle, out long threadUid) private KernelResult GetThreadId(int handle, out long threadUid)
{ {
KThread thread = _process.HandleTable.GetKThread(handle); KThread thread = _process.HandleTable.GetKThread(handle);
@ -299,6 +371,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SetThreadActivity(handle, pause); return SetThreadActivity(handle, pause);
} }
public KernelResult SetThreadActivity32([R(0)] int handle, [R(1)] bool pause)
{
return SetThreadActivity(handle, pause);
}
private KernelResult SetThreadActivity(int handle, bool pause) private KernelResult SetThreadActivity(int handle, bool pause)
{ {
KThread thread = _process.HandleTable.GetObject<KThread>(handle); KThread thread = _process.HandleTable.GetObject<KThread>(handle);
@ -326,6 +403,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return GetThreadContext3(address, handle); return GetThreadContext3(address, handle);
} }
public KernelResult GetThreadContext332([R(0)] uint address, [R(1)] int handle)
{
return GetThreadContext3(address, handle);
}
private KernelResult GetThreadContext3(ulong address, int handle) private KernelResult GetThreadContext3(ulong address, int handle)
{ {
KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

View file

@ -12,6 +12,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex); return WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex);
} }
public KernelResult WaitSynchronization32(
[R(0)] uint timeoutLow,
[R(1)] uint handlesPtr,
[R(2)] int handlesCount,
[R(3)] uint timeoutHigh,
[R(1)] out int handleIndex)
{
long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32));
return WaitSynchronization(handlesPtr, handlesCount, timeout, out handleIndex);
}
private KernelResult WaitSynchronization(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex) private KernelResult WaitSynchronization(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex)
{ {
handleIndex = 0; handleIndex = 0;
@ -45,6 +57,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return CancelSynchronization(handle); return CancelSynchronization(handle);
} }
public KernelResult CancelSynchronization32([R(0)] int handle)
{
return CancelSynchronization(handle);
}
private KernelResult CancelSynchronization(int handle) private KernelResult CancelSynchronization(int handle)
{ {
KThread thread = _process.HandleTable.GetKThread(handle); KThread thread = _process.HandleTable.GetKThread(handle);
@ -64,6 +81,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ArbitrateLock(ownerHandle, mutexAddress, requesterHandle); return ArbitrateLock(ownerHandle, mutexAddress, requesterHandle);
} }
public KernelResult ArbitrateLock32([R(0)] int ownerHandle, [R(1)] uint mutexAddress, [R(2)] int requesterHandle)
{
return ArbitrateLock(ownerHandle, mutexAddress, requesterHandle);
}
private KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle) private KernelResult ArbitrateLock(int ownerHandle, ulong mutexAddress, int requesterHandle)
{ {
if (IsPointingInsideKernel(mutexAddress)) if (IsPointingInsideKernel(mutexAddress))
@ -86,6 +108,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return ArbitrateUnlock(mutexAddress); return ArbitrateUnlock(mutexAddress);
} }
public KernelResult ArbitrateUnlock32([R(0)] uint mutexAddress)
{
return ArbitrateUnlock(mutexAddress);
}
private KernelResult ArbitrateUnlock(ulong mutexAddress) private KernelResult ArbitrateUnlock(ulong mutexAddress)
{ {
if (IsPointingInsideKernel(mutexAddress)) if (IsPointingInsideKernel(mutexAddress))
@ -112,6 +139,18 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout); return WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout);
} }
public KernelResult WaitProcessWideKeyAtomic32(
[R(0)] uint mutexAddress,
[R(1)] uint condVarAddress,
[R(2)] int handle,
[R(3)] uint timeoutLow,
[R(4)] uint timeoutHigh)
{
long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32));
return WaitProcessWideKeyAtomic(mutexAddress, condVarAddress, handle, timeout);
}
private KernelResult WaitProcessWideKeyAtomic( private KernelResult WaitProcessWideKeyAtomic(
ulong mutexAddress, ulong mutexAddress,
ulong condVarAddress, ulong condVarAddress,
@ -142,6 +181,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SignalProcessWideKey(address, count); return SignalProcessWideKey(address, count);
} }
public KernelResult SignalProcessWideKey32([R(0)] uint address, [R(1)] int count)
{
return SignalProcessWideKey(address, count);
}
private KernelResult SignalProcessWideKey(ulong address, int count) private KernelResult SignalProcessWideKey(ulong address, int count)
{ {
KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KProcess currentProcess = _system.Scheduler.GetCurrentProcess();
@ -156,6 +200,13 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return WaitForAddress(address, type, value, timeout); return WaitForAddress(address, type, value, timeout);
} }
public KernelResult WaitForAddress32([R(0)] uint address, [R(1)] ArbitrationType type, [R(2)] int value, [R(3)] uint timeoutLow, [R(4)] uint timeoutHigh)
{
long timeout = (long)(timeoutLow | ((ulong)timeoutHigh << 32));
return WaitForAddress(address, type, value, timeout);
}
private KernelResult WaitForAddress(ulong address, ArbitrationType type, int value, long timeout) private KernelResult WaitForAddress(ulong address, ArbitrationType type, int value, long timeout)
{ {
if (IsPointingInsideKernel(address)) if (IsPointingInsideKernel(address))
@ -199,6 +250,11 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return SignalToAddress(address, type, value, count); return SignalToAddress(address, type, value, count);
} }
public KernelResult SignalToAddress32([R(0)] uint address, [R(1)] SignalType type, [R(2)] int value, [R(3)] int count)
{
return SignalToAddress(address, type, value, count);
}
private KernelResult SignalToAddress(ulong address, SignalType type, int value, int count) private KernelResult SignalToAddress(ulong address, SignalType type, int value, int count)
{ {
if (IsPointingInsideKernel(address)) if (IsPointingInsideKernel(address))