forked from Mirror/Ryujinx
Improve kernel events implementation (#430)
* Improve kernel events implementation * Some cleanup * Address PR feedback
This commit is contained in:
parent
54ed9096bd
commit
7de7b559ad
38 changed files with 597 additions and 161 deletions
|
@ -71,6 +71,8 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
Withholders = new LinkedList<KThread>();
|
Withholders = new LinkedList<KThread>();
|
||||||
|
|
||||||
|
Scheduler.StartAutoPreemptionThread();
|
||||||
|
|
||||||
if (!Device.Memory.Allocator.TryAllocate(HidSize, out long HidPA) ||
|
if (!Device.Memory.Allocator.TryAllocate(HidSize, out long HidPA) ||
|
||||||
!Device.Memory.Allocator.TryAllocate(FontSize, out long FontPA))
|
!Device.Memory.Allocator.TryAllocate(FontSize, out long FontPA))
|
||||||
{
|
{
|
||||||
|
@ -466,7 +468,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
public void SignalVsync()
|
public void SignalVsync()
|
||||||
{
|
{
|
||||||
VsyncEvent.Signal();
|
VsyncEvent.ReadableEvent.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Process MakeProcess(Npdm MetaData = null)
|
private Process MakeProcess(Npdm MetaData = null)
|
||||||
|
|
|
@ -73,7 +73,10 @@ namespace Ryujinx.HLE.HOS.Ipc
|
||||||
{
|
{
|
||||||
int Unknown = ReqReader.ReadInt32();
|
int Unknown = ReqReader.ReadInt32();
|
||||||
|
|
||||||
int Handle = Process.HandleTable.OpenHandle(Session);
|
if (Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,15 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
private bool KeepPreempting;
|
private bool KeepPreempting;
|
||||||
|
|
||||||
|
public void StartAutoPreemptionThread()
|
||||||
|
{
|
||||||
|
Thread PreemptionThread = new Thread(PreemptCurrentThread);
|
||||||
|
|
||||||
|
KeepPreempting = true;
|
||||||
|
|
||||||
|
PreemptionThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
public void ContextSwitch()
|
public void ContextSwitch()
|
||||||
{
|
{
|
||||||
lock (CoreContexts)
|
lock (CoreContexts)
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread MutexOwner = Process.HandleTable.GetData<KThread>(OwnerHandle);
|
KThread MutexOwner = Process.HandleTable.GetObject<KThread>(OwnerHandle);
|
||||||
|
|
||||||
if (MutexOwner == null)
|
if (MutexOwner == null)
|
||||||
{
|
{
|
||||||
|
@ -282,7 +282,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
MutexValue &= ~HasListenersMask;
|
MutexValue &= ~HasListenersMask;
|
||||||
|
|
||||||
KThread MutexOwner = Process.HandleTable.GetData<KThread>(MutexValue);
|
KThread MutexOwner = Process.HandleTable.GetObject<KThread>(MutexValue);
|
||||||
|
|
||||||
if (MutexOwner != null)
|
if (MutexOwner != null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,38 +1,14 @@
|
||||||
namespace Ryujinx.HLE.HOS.Kernel
|
namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
class KEvent : KSynchronizationObject
|
class KEvent
|
||||||
{
|
{
|
||||||
private bool Signaled;
|
public KReadableEvent ReadableEvent { get; private set; }
|
||||||
|
public KWritableEvent WritableEvent { get; private set; }
|
||||||
|
|
||||||
public string Name { get; private set; }
|
public KEvent(Horizon System)
|
||||||
|
|
||||||
public KEvent(Horizon System, string Name = "") : base(System)
|
|
||||||
{
|
{
|
||||||
this.Name = Name;
|
ReadableEvent = new KReadableEvent(System, this);
|
||||||
}
|
WritableEvent = new KWritableEvent(this);
|
||||||
|
|
||||||
public override void Signal()
|
|
||||||
{
|
|
||||||
System.CriticalSectionLock.Lock();
|
|
||||||
|
|
||||||
if (!Signaled)
|
|
||||||
{
|
|
||||||
Signaled = true;
|
|
||||||
|
|
||||||
base.Signal();
|
|
||||||
}
|
|
||||||
|
|
||||||
System.CriticalSectionLock.Unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Reset()
|
|
||||||
{
|
|
||||||
Signaled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsSignaled()
|
|
||||||
{
|
|
||||||
return Signaled;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
17
Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs
Normal file
17
Ryujinx.HLE/HOS/Kernel/KHandleEntry.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
{
|
||||||
|
class KHandleEntry
|
||||||
|
{
|
||||||
|
public KHandleEntry Next { get; set; }
|
||||||
|
|
||||||
|
public int Index { get; private set; }
|
||||||
|
|
||||||
|
public ushort HandleId { get; set; }
|
||||||
|
public object Obj { get; set; }
|
||||||
|
|
||||||
|
public KHandleEntry(int Index)
|
||||||
|
{
|
||||||
|
this.Index = Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,34 +1,183 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel
|
namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
class KProcessHandleTable
|
class KProcessHandleTable
|
||||||
{
|
{
|
||||||
private IdDictionary Handles;
|
private const int SelfThreadHandle = (0x1ffff << 15) | 0;
|
||||||
|
private const int SelfProcessHandle = (0x1ffff << 15) | 1;
|
||||||
|
|
||||||
public KProcessHandleTable()
|
private Horizon System;
|
||||||
|
|
||||||
|
private KHandleEntry[] Table;
|
||||||
|
|
||||||
|
private KHandleEntry TableHead;
|
||||||
|
private KHandleEntry NextFreeEntry;
|
||||||
|
|
||||||
|
private int ActiveSlotsCount;
|
||||||
|
|
||||||
|
private int Size;
|
||||||
|
|
||||||
|
private ushort IdCounter;
|
||||||
|
|
||||||
|
private object LockObj;
|
||||||
|
|
||||||
|
public KProcessHandleTable(Horizon System, int Size = 1024)
|
||||||
{
|
{
|
||||||
Handles = new IdDictionary();
|
this.System = System;
|
||||||
|
this.Size = Size;
|
||||||
|
|
||||||
|
IdCounter = 1;
|
||||||
|
|
||||||
|
Table = new KHandleEntry[Size];
|
||||||
|
|
||||||
|
TableHead = new KHandleEntry(0);
|
||||||
|
|
||||||
|
KHandleEntry Entry = TableHead;
|
||||||
|
|
||||||
|
for (int Index = 0; Index < Size; Index++)
|
||||||
|
{
|
||||||
|
Table[Index] = Entry;
|
||||||
|
|
||||||
|
Entry.Next = new KHandleEntry(Index + 1);
|
||||||
|
|
||||||
|
Entry = Entry.Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
Table[Size - 1].Next = null;
|
||||||
|
|
||||||
|
NextFreeEntry = TableHead;
|
||||||
|
|
||||||
|
LockObj = new object();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int OpenHandle(object Obj)
|
public KernelResult GenerateHandle(object Obj, out int Handle)
|
||||||
{
|
{
|
||||||
return Handles.Add(Obj);
|
Handle = 0;
|
||||||
|
|
||||||
|
lock (LockObj)
|
||||||
|
{
|
||||||
|
if (ActiveSlotsCount >= Size)
|
||||||
|
{
|
||||||
|
return KernelResult.HandleTableFull;
|
||||||
|
}
|
||||||
|
|
||||||
|
KHandleEntry Entry = NextFreeEntry;
|
||||||
|
|
||||||
|
NextFreeEntry = Entry.Next;
|
||||||
|
|
||||||
|
Entry.Obj = Obj;
|
||||||
|
Entry.HandleId = IdCounter;
|
||||||
|
|
||||||
|
ActiveSlotsCount++;
|
||||||
|
|
||||||
|
Handle = (int)((IdCounter << 15) & (uint)0xffff8000) | Entry.Index;
|
||||||
|
|
||||||
|
if ((short)(IdCounter + 1) >= 0)
|
||||||
|
{
|
||||||
|
IdCounter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IdCounter = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return KernelResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetData<T>(int Handle)
|
public bool CloseHandle(int Handle)
|
||||||
{
|
{
|
||||||
return Handles.GetData<T>(Handle);
|
if ((Handle >> 30) != 0 ||
|
||||||
|
Handle == SelfThreadHandle ||
|
||||||
|
Handle == SelfProcessHandle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Index = (Handle >> 0) & 0x7fff;
|
||||||
|
int HandleId = (Handle >> 15);
|
||||||
|
|
||||||
|
bool Result = false;
|
||||||
|
|
||||||
|
lock (LockObj)
|
||||||
|
{
|
||||||
|
if (HandleId != 0 && Index < Size)
|
||||||
|
{
|
||||||
|
KHandleEntry Entry = Table[Index];
|
||||||
|
|
||||||
|
if (Entry.Obj != null && Entry.HandleId == HandleId)
|
||||||
|
{
|
||||||
|
Entry.Obj = null;
|
||||||
|
Entry.Next = NextFreeEntry;
|
||||||
|
|
||||||
|
NextFreeEntry = Entry;
|
||||||
|
|
||||||
|
ActiveSlotsCount--;
|
||||||
|
|
||||||
|
Result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object CloseHandle(int Handle)
|
public T GetObject<T>(int Handle)
|
||||||
{
|
{
|
||||||
return Handles.Delete(Handle);
|
int Index = (Handle >> 0) & 0x7fff;
|
||||||
|
int HandleId = (Handle >> 15);
|
||||||
|
|
||||||
|
lock (LockObj)
|
||||||
|
{
|
||||||
|
if ((Handle >> 30) == 0 && HandleId != 0)
|
||||||
|
{
|
||||||
|
KHandleEntry Entry = Table[Index];
|
||||||
|
|
||||||
|
if (Entry.HandleId == HandleId && Entry.Obj is T Obj)
|
||||||
|
{
|
||||||
|
return Obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ICollection<object> Clear()
|
public KThread GetKThread(int Handle)
|
||||||
{
|
{
|
||||||
return Handles.Clear();
|
if (Handle == SelfThreadHandle)
|
||||||
|
{
|
||||||
|
return System.Scheduler.GetCurrentThread();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return GetObject<KThread>(Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Destroy()
|
||||||
|
{
|
||||||
|
lock (LockObj)
|
||||||
|
{
|
||||||
|
for (int Index = 0; Index < Size; Index++)
|
||||||
|
{
|
||||||
|
KHandleEntry Entry = Table[Index];
|
||||||
|
|
||||||
|
if (Entry.Obj != null)
|
||||||
|
{
|
||||||
|
if (Entry.Obj is IDisposable DisposableObj)
|
||||||
|
{
|
||||||
|
DisposableObj.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry.Obj = null;
|
||||||
|
Entry.Next = NextFreeEntry;
|
||||||
|
|
||||||
|
NextFreeEntry = Entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
62
Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs
Normal file
62
Ryujinx.HLE/HOS/Kernel/KReadableEvent.cs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
{
|
||||||
|
class KReadableEvent : KSynchronizationObject
|
||||||
|
{
|
||||||
|
private KEvent Parent;
|
||||||
|
|
||||||
|
private bool Signaled;
|
||||||
|
|
||||||
|
public KReadableEvent(Horizon System, KEvent Parent) : base(System)
|
||||||
|
{
|
||||||
|
this.Parent = Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Signal()
|
||||||
|
{
|
||||||
|
System.CriticalSectionLock.Lock();
|
||||||
|
|
||||||
|
if (!Signaled)
|
||||||
|
{
|
||||||
|
Signaled = true;
|
||||||
|
|
||||||
|
base.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.CriticalSectionLock.Unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult Clear()
|
||||||
|
{
|
||||||
|
Signaled = false;
|
||||||
|
|
||||||
|
return KernelResult.Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult ClearIfSignaled()
|
||||||
|
{
|
||||||
|
KernelResult Result;
|
||||||
|
|
||||||
|
System.CriticalSectionLock.Lock();
|
||||||
|
|
||||||
|
if (Signaled)
|
||||||
|
{
|
||||||
|
Signaled = false;
|
||||||
|
|
||||||
|
Result = KernelResult.Success;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = KernelResult.InvalidState;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.CriticalSectionLock.Unlock();
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsSignaled()
|
||||||
|
{
|
||||||
|
return Signaled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Kernel
|
namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
|
@ -35,12 +34,6 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
CoreContexts[Core] = new KCoreContext(this, CoreManager);
|
CoreContexts[Core] = new KCoreContext(this, CoreManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread PreemptionThread = new Thread(PreemptCurrentThread);
|
|
||||||
|
|
||||||
KeepPreempting = true;
|
|
||||||
|
|
||||||
PreemptionThread.Start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PreemptThreads()
|
private void PreemptThreads()
|
||||||
|
|
22
Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs
Normal file
22
Ryujinx.HLE/HOS/Kernel/KWritableEvent.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
{
|
||||||
|
class KWritableEvent
|
||||||
|
{
|
||||||
|
private KEvent Parent;
|
||||||
|
|
||||||
|
public KWritableEvent(KEvent Parent)
|
||||||
|
{
|
||||||
|
this.Parent = Parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Signal()
|
||||||
|
{
|
||||||
|
Parent.ReadableEvent.Signal();
|
||||||
|
}
|
||||||
|
|
||||||
|
public KernelResult Clear()
|
||||||
|
{
|
||||||
|
return Parent.ReadableEvent.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
public const int InvalidSize = 101;
|
public const int InvalidSize = 101;
|
||||||
public const int InvalidAddress = 102;
|
public const int InvalidAddress = 102;
|
||||||
public const int OutOfMemory = 104;
|
public const int OutOfMemory = 104;
|
||||||
|
public const int HandleTableFull = 105;
|
||||||
public const int NoAccessPerm = 106;
|
public const int NoAccessPerm = 106;
|
||||||
public const int InvalidPermission = 108;
|
public const int InvalidPermission = 108;
|
||||||
public const int InvalidMemRange = 110;
|
public const int InvalidMemRange = 110;
|
||||||
|
|
10
Ryujinx.HLE/HOS/Kernel/KernelResult.cs
Normal file
10
Ryujinx.HLE/HOS/Kernel/KernelResult.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
{
|
||||||
|
enum KernelResult
|
||||||
|
{
|
||||||
|
Success = 0,
|
||||||
|
HandleTableFull = 0xd201,
|
||||||
|
InvalidHandle = 0xe401,
|
||||||
|
InvalidState = 0xfa01
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,9 +39,6 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private const uint SelfThreadHandle = 0xffff8000;
|
|
||||||
private const uint SelfProcessHandle = 0xffff8001;
|
|
||||||
|
|
||||||
private static Random Rng;
|
private static Random Rng;
|
||||||
|
|
||||||
public SvcHandler(Switch Device, Process Process)
|
public SvcHandler(Switch Device, Process Process)
|
||||||
|
@ -63,12 +60,13 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{ 0x0e, SvcGetThreadCoreMask },
|
{ 0x0e, SvcGetThreadCoreMask },
|
||||||
{ 0x0f, SvcSetThreadCoreMask },
|
{ 0x0f, SvcSetThreadCoreMask },
|
||||||
{ 0x10, SvcGetCurrentProcessorNumber },
|
{ 0x10, SvcGetCurrentProcessorNumber },
|
||||||
{ 0x12, SvcClearEvent },
|
{ 0x11, SignalEvent64 },
|
||||||
|
{ 0x12, ClearEvent64 },
|
||||||
{ 0x13, SvcMapSharedMemory },
|
{ 0x13, SvcMapSharedMemory },
|
||||||
{ 0x14, SvcUnmapSharedMemory },
|
{ 0x14, SvcUnmapSharedMemory },
|
||||||
{ 0x15, SvcCreateTransferMemory },
|
{ 0x15, SvcCreateTransferMemory },
|
||||||
{ 0x16, SvcCloseHandle },
|
{ 0x16, SvcCloseHandle },
|
||||||
{ 0x17, SvcResetSignal },
|
{ 0x17, ResetSignal64 },
|
||||||
{ 0x18, SvcWaitSynchronization },
|
{ 0x18, SvcWaitSynchronization },
|
||||||
{ 0x19, SvcCancelSynchronization },
|
{ 0x19, SvcCancelSynchronization },
|
||||||
{ 0x1a, SvcArbitrateLock },
|
{ 0x1a, SvcArbitrateLock },
|
||||||
|
@ -88,7 +86,8 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{ 0x32, SvcSetThreadActivity },
|
{ 0x32, SvcSetThreadActivity },
|
||||||
{ 0x33, SvcGetThreadContext3 },
|
{ 0x33, SvcGetThreadContext3 },
|
||||||
{ 0x34, SvcWaitForAddress },
|
{ 0x34, SvcWaitForAddress },
|
||||||
{ 0x35, SvcSignalToAddress }
|
{ 0x35, SvcSignalToAddress },
|
||||||
|
{ 0x45, CreateEvent64 }
|
||||||
};
|
};
|
||||||
|
|
||||||
this.Device = Device;
|
this.Device = Device;
|
||||||
|
@ -123,17 +122,5 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
throw new NotImplementedException($"0x{e.Id:x4}");
|
throw new NotImplementedException($"0x{e.Id:x4}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private KThread GetThread(long Tpidr, int Handle)
|
|
||||||
{
|
|
||||||
if ((uint)Handle == SelfThreadHandle)
|
|
||||||
{
|
|
||||||
return Process.GetThread(Tpidr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return Process.HandleTable.GetData<KThread>(Handle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -276,7 +276,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle);
|
KSharedMemory SharedMemory = Process.HandleTable.GetObject<KSharedMemory>(Handle);
|
||||||
|
|
||||||
if (SharedMemory == null)
|
if (SharedMemory == null)
|
||||||
{
|
{
|
||||||
|
@ -348,7 +348,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KSharedMemory SharedMemory = Process.HandleTable.GetData<KSharedMemory>(Handle);
|
KSharedMemory SharedMemory = Process.HandleTable.GetObject<KSharedMemory>(Handle);
|
||||||
|
|
||||||
if (SharedMemory == null)
|
if (SharedMemory == null)
|
||||||
{
|
{
|
||||||
|
@ -425,9 +425,9 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
KTransferMemory TransferMemory = new KTransferMemory(Position, Size);
|
KTransferMemory TransferMemory = new KTransferMemory(Position, Size);
|
||||||
|
|
||||||
int Handle = Process.HandleTable.OpenHandle(TransferMemory);
|
KernelResult Result = Process.HandleTable.GenerateHandle(TransferMemory, out int Handle);
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = (uint)Result;
|
||||||
ThreadState.X1 = (ulong)Handle;
|
ThreadState.X1 = (ulong)Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,20 +22,73 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
Device.System.ExitProcess(Process.ProcessId);
|
Device.System.ExitProcess(Process.ProcessId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcClearEvent(AThreadState ThreadState)
|
private void SignalEvent64(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
ThreadState.X0 = (ulong)SignalEvent((int)ThreadState.X0);
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: Implement events.
|
private KernelResult SignalEvent(int Handle)
|
||||||
|
{
|
||||||
|
KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle);
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
KernelResult Result;
|
||||||
|
|
||||||
|
if (WritableEvent != null)
|
||||||
|
{
|
||||||
|
WritableEvent.Signal();
|
||||||
|
|
||||||
|
Result = KernelResult.Success;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = KernelResult.InvalidHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearEvent64(AThreadState ThreadState)
|
||||||
|
{
|
||||||
|
ThreadState.X0 = (ulong)ClearEvent((int)ThreadState.X0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private KernelResult ClearEvent(int Handle)
|
||||||
|
{
|
||||||
|
KernelResult Result;
|
||||||
|
|
||||||
|
KWritableEvent WritableEvent = Process.HandleTable.GetObject<KWritableEvent>(Handle);
|
||||||
|
|
||||||
|
if (WritableEvent == null)
|
||||||
|
{
|
||||||
|
KReadableEvent ReadableEvent = Process.HandleTable.GetObject<KReadableEvent>(Handle);
|
||||||
|
|
||||||
|
Result = ReadableEvent?.Clear() ?? KernelResult.InvalidHandle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Result = WritableEvent.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcCloseHandle(AThreadState ThreadState)
|
private void SvcCloseHandle(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
|
|
||||||
object Obj = Process.HandleTable.CloseHandle(Handle);
|
object Obj = Process.HandleTable.GetObject<object>(Handle);
|
||||||
|
|
||||||
|
Process.HandleTable.CloseHandle(Handle);
|
||||||
|
|
||||||
if (Obj == null)
|
if (Obj == null)
|
||||||
{
|
{
|
||||||
|
@ -60,24 +113,37 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcResetSignal(AThreadState ThreadState)
|
private void ResetSignal64(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
ThreadState.X0 = (ulong)ResetSignal((int)ThreadState.X0);
|
||||||
|
}
|
||||||
|
|
||||||
KEvent Event = Process.HandleTable.GetData<KEvent>(Handle);
|
private KernelResult ResetSignal(int Handle)
|
||||||
|
{
|
||||||
|
KReadableEvent ReadableEvent = Process.HandleTable.GetObject<KReadableEvent>(Handle);
|
||||||
|
|
||||||
if (Event != null)
|
KernelResult Result;
|
||||||
|
|
||||||
|
//TODO: KProcess support.
|
||||||
|
if (ReadableEvent != null)
|
||||||
{
|
{
|
||||||
Event.Reset();
|
Result = ReadableEvent.ClearIfSignaled();
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid event handle 0x{Handle:x8}!");
|
Result = KernelResult.InvalidHandle;
|
||||||
|
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Result == KernelResult.InvalidState)
|
||||||
|
{
|
||||||
|
Device.Log.PrintDebug(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
|
||||||
|
}
|
||||||
|
else if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
Device.Log.PrintWarning(LogClass.KernelSvc, "Operation failed with error: " + Result + "!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcGetSystemTick(AThreadState ThreadState)
|
private void SvcGetSystemTick(AThreadState ThreadState)
|
||||||
|
@ -96,10 +162,13 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
//actually exists, return error codes otherwise.
|
//actually exists, return error codes otherwise.
|
||||||
KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name);
|
KSession Session = new KSession(ServiceFactory.MakeService(System, Name), Name);
|
||||||
|
|
||||||
ulong Handle = (ulong)Process.HandleTable.OpenHandle(Session);
|
if (Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
ThreadState.X1 = Handle;
|
ThreadState.X1 = (uint)Handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SvcSendSyncRequest(AThreadState ThreadState)
|
private void SvcSendSyncRequest(AThreadState ThreadState)
|
||||||
|
@ -122,7 +191,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);
|
byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);
|
||||||
|
|
||||||
KSession Session = Process.HandleTable.GetData<KSession>(Handle);
|
KSession Session = Process.HandleTable.GetObject<KSession>(Handle);
|
||||||
|
|
||||||
if (Session != null)
|
if (Session != null)
|
||||||
{
|
{
|
||||||
|
@ -206,7 +275,8 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
if (InfoType == 18 ||
|
if (InfoType == 18 ||
|
||||||
InfoType == 19 ||
|
InfoType == 19 ||
|
||||||
InfoType == 20 ||
|
InfoType == 20 ||
|
||||||
InfoType == 21)
|
InfoType == 21 ||
|
||||||
|
InfoType == 22)
|
||||||
{
|
{
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
|
||||||
|
|
||||||
|
@ -287,5 +357,37 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
ThreadState.X0 = 0;
|
ThreadState.X0 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CreateEvent64(AThreadState State)
|
||||||
|
{
|
||||||
|
KernelResult Result = CreateEvent(out int WEventHandle, out int REventHandle);
|
||||||
|
|
||||||
|
State.X0 = (ulong)Result;
|
||||||
|
State.X1 = (ulong)WEventHandle;
|
||||||
|
State.X2 = (ulong)REventHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private KernelResult CreateEvent(out int WEventHandle, out int REventHandle)
|
||||||
|
{
|
||||||
|
KEvent Event = new KEvent(System);
|
||||||
|
|
||||||
|
KernelResult Result = Process.HandleTable.GenerateHandle(Event.WritableEvent, out WEventHandle);
|
||||||
|
|
||||||
|
if (Result == KernelResult.Success)
|
||||||
|
{
|
||||||
|
Result = Process.HandleTable.GenerateHandle(Event.ReadableEvent, out REventHandle);
|
||||||
|
|
||||||
|
if (Result != KernelResult.Success)
|
||||||
|
{
|
||||||
|
Process.HandleTable.CloseHandle(WEventHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
REventHandle = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
|
|
||||||
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -112,7 +112,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X1;
|
int Handle = (int)ThreadState.X1;
|
||||||
|
|
||||||
KThread Thread = GetThread(ThreadState.Tpidr, Handle);
|
KThread Thread = Process.HandleTable.GetKThread(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -138,7 +138,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
//TODO: NPDM check.
|
//TODO: NPDM check.
|
||||||
|
|
||||||
KThread Thread = GetThread(ThreadState.Tpidr, Handle);
|
KThread Thread = Process.HandleTable.GetKThread(Handle);
|
||||||
|
|
||||||
if (Thread == null)
|
if (Thread == null)
|
||||||
{
|
{
|
||||||
|
@ -160,7 +160,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
Device.Log.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + Handle.ToString("x8"));
|
Device.Log.PrintDebug(LogClass.KernelSvc, "Handle = 0x" + Handle.ToString("x8"));
|
||||||
|
|
||||||
KThread Thread = GetThread(ThreadState.Tpidr, Handle);
|
KThread Thread = Process.HandleTable.GetKThread(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -178,12 +178,12 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
private void SvcSetThreadCoreMask(AThreadState ThreadState)
|
private void SvcSetThreadCoreMask(AThreadState ThreadState)
|
||||||
{
|
{
|
||||||
int ThreadHandle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
int PrefferedCore = (int)ThreadState.X1;
|
int PrefferedCore = (int)ThreadState.X1;
|
||||||
long AffinityMask = (long)ThreadState.X2;
|
long AffinityMask = (long)ThreadState.X2;
|
||||||
|
|
||||||
Device.Log.PrintDebug(LogClass.KernelSvc,
|
Device.Log.PrintDebug(LogClass.KernelSvc,
|
||||||
"ThreadHandle = 0x" + ThreadHandle .ToString("x8") + ", " +
|
"Handle = 0x" + Handle .ToString("x8") + ", " +
|
||||||
"PrefferedCore = 0x" + PrefferedCore.ToString("x8") + ", " +
|
"PrefferedCore = 0x" + PrefferedCore.ToString("x8") + ", " +
|
||||||
"AffinityMask = 0x" + AffinityMask .ToString("x16"));
|
"AffinityMask = 0x" + AffinityMask .ToString("x16"));
|
||||||
|
|
||||||
|
@ -219,11 +219,11 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread Thread = GetThread(ThreadState.Tpidr, ThreadHandle);
|
KThread Thread = Process.HandleTable.GetKThread(Handle);
|
||||||
|
|
||||||
if (Thread == null)
|
if (Thread == null)
|
||||||
{
|
{
|
||||||
Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{ThreadHandle:x8}!");
|
Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
|
||||||
|
|
||||||
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
{
|
{
|
||||||
int Handle = (int)ThreadState.X1;
|
int Handle = (int)ThreadState.X1;
|
||||||
|
|
||||||
KThread Thread = GetThread(ThreadState.Tpidr, Handle);
|
KThread Thread = Process.HandleTable.GetKThread(Handle);
|
||||||
|
|
||||||
if (Thread != null)
|
if (Thread != null)
|
||||||
{
|
{
|
||||||
|
@ -269,7 +269,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
int Handle = (int)ThreadState.X0;
|
int Handle = (int)ThreadState.X0;
|
||||||
bool Pause = (int)ThreadState.X1 == 1;
|
bool Pause = (int)ThreadState.X1 == 1;
|
||||||
|
|
||||||
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread == null)
|
if (Thread == null)
|
||||||
{
|
{
|
||||||
|
@ -304,7 +304,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
long Position = (long)ThreadState.X0;
|
long Position = (long)ThreadState.X0;
|
||||||
int Handle = (int)ThreadState.X1;
|
int Handle = (int)ThreadState.X1;
|
||||||
|
|
||||||
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
|
KThread Thread = Process.HandleTable.GetObject<KThread>(Handle);
|
||||||
|
|
||||||
if (Thread == null)
|
if (Thread == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using ChocolArm64.State;
|
using ChocolArm64.State;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.HLE.HOS.ErrorCode;
|
using static Ryujinx.HLE.HOS.ErrorCode;
|
||||||
|
|
||||||
|
@ -25,22 +26,27 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KSynchronizationObject[] SyncObjs = new KSynchronizationObject[HandlesCount];
|
List<KSynchronizationObject> SyncObjs = new List<KSynchronizationObject>();
|
||||||
|
|
||||||
for (int Index = 0; Index < HandlesCount; Index++)
|
for (int Index = 0; Index < HandlesCount; Index++)
|
||||||
{
|
{
|
||||||
int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
|
int Handle = Memory.ReadInt32(HandlesPtr + Index * 4);
|
||||||
|
|
||||||
KSynchronizationObject SyncObj = Process.HandleTable.GetData<KSynchronizationObject>(Handle);
|
KSynchronizationObject SyncObj = Process.HandleTable.GetObject<KSynchronizationObject>(Handle);
|
||||||
|
|
||||||
SyncObjs[Index] = SyncObj;
|
if (SyncObj == null)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SyncObjs.Add(SyncObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
int HndIndex = (int)ThreadState.X1;
|
int HndIndex = (int)ThreadState.X1;
|
||||||
|
|
||||||
ulong High = ThreadState.X1 & (0xffffffffUL << 32);
|
ulong High = ThreadState.X1 & (0xffffffffUL << 32);
|
||||||
|
|
||||||
long Result = System.Synchronization.WaitFor(SyncObjs, Timeout, ref HndIndex);
|
long Result = System.Synchronization.WaitFor(SyncObjs.ToArray(), Timeout, ref HndIndex);
|
||||||
|
|
||||||
if (Result != 0)
|
if (Result != 0)
|
||||||
{
|
{
|
||||||
|
@ -65,7 +71,7 @@ namespace Ryujinx.HLE.HOS.Kernel
|
||||||
|
|
||||||
Device.Log.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + ThreadHandle.ToString("x8"));
|
Device.Log.PrintDebug(LogClass.KernelSvc, "ThreadHandle = 0x" + ThreadHandle.ToString("x8"));
|
||||||
|
|
||||||
KThread Thread = Process.HandleTable.GetData<KThread>(ThreadHandle);
|
KThread Thread = Process.HandleTable.GetKThread(ThreadHandle);
|
||||||
|
|
||||||
if (Thread == null)
|
if (Thread == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,7 +71,22 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
TlsPages = new List<KTlsPageManager>();
|
TlsPages = new List<KTlsPageManager>();
|
||||||
|
|
||||||
HandleTable = new KProcessHandleTable();
|
int HandleTableSize = 1024;
|
||||||
|
|
||||||
|
if (MetaData != null)
|
||||||
|
{
|
||||||
|
foreach (KernelAccessControlItem Item in MetaData.ACI0.KernelAccessControl.Items)
|
||||||
|
{
|
||||||
|
if (Item.HasHandleTableSize)
|
||||||
|
{
|
||||||
|
HandleTableSize = Item.HandleTableSize;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleTable = new KProcessHandleTable(Device.System, HandleTableSize);
|
||||||
|
|
||||||
AppletState = new AppletStateMgr(Device.System);
|
AppletState = new AppletStateMgr(Device.System);
|
||||||
|
|
||||||
|
@ -139,7 +154,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
KThread MainThread = HandleTable.GetData<KThread>(Handle);
|
KThread MainThread = HandleTable.GetKThread(Handle);
|
||||||
|
|
||||||
if (NeedsHbAbi)
|
if (NeedsHbAbi)
|
||||||
{
|
{
|
||||||
|
@ -190,7 +205,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
Thread.LastPc = EntryPoint;
|
Thread.LastPc = EntryPoint;
|
||||||
|
|
||||||
int Handle = HandleTable.OpenHandle(Thread);
|
HandleTable.GenerateHandle(Thread, out int Handle);
|
||||||
|
|
||||||
CpuThread.ThreadState.CntfrqEl0 = TickFreq;
|
CpuThread.ThreadState.CntfrqEl0 = TickFreq;
|
||||||
CpuThread.ThreadState.Tpidr = Tpidr;
|
CpuThread.ThreadState.Tpidr = Tpidr;
|
||||||
|
@ -427,13 +442,7 @@ namespace Ryujinx.HLE.HOS
|
||||||
|
|
||||||
Disposed = true;
|
Disposed = true;
|
||||||
|
|
||||||
foreach (object Obj in HandleTable.Clear())
|
HandleTable.Destroy();
|
||||||
{
|
|
||||||
if (Obj is KSession Session)
|
|
||||||
{
|
|
||||||
Session.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
INvDrvServices.UnloadProcess(this);
|
INvDrvServices.UnloadProcess(this);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using static Ryujinx.HLE.HOS.ErrorCode;
|
using static Ryujinx.HLE.HOS.ErrorCode;
|
||||||
|
@ -36,7 +37,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
{
|
{
|
||||||
KEvent Event = Context.Process.AppletState.MessageEvent;
|
KEvent Event = Context.Process.AppletState.MessageEvent;
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(Event);
|
if (Context.Process.HandleTable.GenerateHandle(Event.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
@ -103,7 +107,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
|
|
||||||
public long GetDefaultDisplayResolutionChangeEvent(ServiceCtx Context)
|
public long GetDefaultDisplayResolutionChangeEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(DisplayResolutionChangeEvent);
|
if (Context.Process.HandleTable.GenerateHandle(DisplayResolutionChangeEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am
|
namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
|
@ -34,7 +35,10 @@ namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
|
|
||||||
public long GetPopFromGeneralChannelEvent(ServiceCtx Context)
|
public long GetPopFromGeneralChannelEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(ChannelEvent);
|
if (Context.Process.HandleTable.GenerateHandle(ChannelEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am
|
namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
|
@ -29,9 +30,12 @@ namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
|
|
||||||
public long GetAppletStateChangedEvent(ServiceCtx Context)
|
public long GetAppletStateChangedEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
StateChangedEvent.Signal();
|
StateChangedEvent.ReadableEvent.Signal();
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(StateChangedEvent);
|
if (Context.Process.HandleTable.GenerateHandle(StateChangedEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Am
|
namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
|
@ -57,9 +58,12 @@ namespace Ryujinx.HLE.HOS.Services.Am
|
||||||
|
|
||||||
public long GetLibraryAppletLaunchableEvent(ServiceCtx Context)
|
public long GetLibraryAppletLaunchableEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
LaunchableEvent.Signal();
|
LaunchableEvent.ReadableEvent.Signal();
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(LaunchableEvent);
|
if (Context.Process.HandleTable.GenerateHandle(LaunchableEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -67,7 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioOut
|
||||||
|
|
||||||
public long RegisterBufferEvent(ServiceCtx Context)
|
public long RegisterBufferEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(ReleaseEvent);
|
if (Context.Process.HandleTable.GenerateHandle(ReleaseEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
||||||
|
|
||||||
private void AudioCallback()
|
private void AudioCallback()
|
||||||
{
|
{
|
||||||
UpdateEvent.Signal();
|
UpdateEvent.ReadableEvent.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T[] CreateArray<T>(int Size) where T : new()
|
private static T[] CreateArray<T>(int Size) where T : new()
|
||||||
|
@ -218,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud.AudioRenderer
|
||||||
|
|
||||||
public long QuerySystemEvent(ServiceCtx Context)
|
public long QuerySystemEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(UpdateEvent);
|
if (Context.Process.HandleTable.GenerateHandle(UpdateEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.HOS.SystemState;
|
using Ryujinx.HLE.HOS.SystemState;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
||||||
SystemEvent = new KEvent(System);
|
SystemEvent = new KEvent(System);
|
||||||
|
|
||||||
//TODO: We shouldn't be signaling this here.
|
//TODO: We shouldn't be signaling this here.
|
||||||
SystemEvent.Signal();
|
SystemEvent.ReadableEvent.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long ListAudioDeviceName(ServiceCtx Context)
|
public long ListAudioDeviceName(ServiceCtx Context)
|
||||||
|
@ -107,7 +108,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
||||||
|
|
||||||
public long QueryAudioDeviceSystemEvent(ServiceCtx Context)
|
public long QueryAudioDeviceSystemEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
|
if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
@ -200,7 +204,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
||||||
|
|
||||||
public long QueryAudioDeviceInputEvent(ServiceCtx Context)
|
public long QueryAudioDeviceInputEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
|
if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
@ -211,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
||||||
|
|
||||||
public long QueryAudioDeviceOutputEvent(ServiceCtx Context)
|
public long QueryAudioDeviceOutputEvent(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(SystemEvent);
|
if (Context.Process.HandleTable.GenerateHandle(SystemEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -150,7 +150,7 @@ namespace Ryujinx.HLE.HOS.Services.Aud
|
||||||
|
|
||||||
ReleaseCallback Callback = () =>
|
ReleaseCallback Callback = () =>
|
||||||
{
|
{
|
||||||
ReleaseEvent.Signal();
|
ReleaseEvent.ReadableEvent.Signal();
|
||||||
};
|
};
|
||||||
|
|
||||||
IAalOutput AudioOut = Context.Device.AudioOut;
|
IAalOutput AudioOut = Context.Device.AudioOut;
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Hid
|
namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
|
@ -24,7 +25,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
|
|
||||||
public long GetSharedMemoryHandle(ServiceCtx Context)
|
public long GetSharedMemoryHandle(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(HidSharedMem);
|
if (Context.Process.HandleTable.GenerateHandle(HidSharedMem, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@ using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Input;
|
using Ryujinx.HLE.Input;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
using Ryujinx.HLE.Utilities;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -219,7 +218,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
{
|
{
|
||||||
long XpadId = Context.RequestData.ReadInt64();
|
long XpadId = Context.RequestData.ReadInt64();
|
||||||
|
|
||||||
XpadIdEventHandle = Context.Process.HandleTable.OpenHandle(XpadIdEvent);
|
if (Context.Process.HandleTable.GenerateHandle(XpadIdEvent, out XpadIdEventHandle) == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(XpadIdEventHandle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(XpadIdEventHandle);
|
||||||
|
|
||||||
|
@ -712,7 +714,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
int NpadId = Context.RequestData.ReadInt32();
|
int NpadId = Context.RequestData.ReadInt32();
|
||||||
long NpadStyleSet = Context.RequestData.ReadInt64();
|
long NpadStyleSet = Context.RequestData.ReadInt64();
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(NpadStyleSetUpdateEvent);
|
if (Context.Process.HandleTable.GenerateHandle(NpadStyleSetUpdateEvent, out int Handle) == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
@ -1351,7 +1356,10 @@ namespace Ryujinx.HLE.HOS.Services.Hid
|
||||||
{
|
{
|
||||||
int PalmaConnectionHandle = Context.RequestData.ReadInt32();
|
int PalmaConnectionHandle = Context.RequestData.ReadInt32();
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(PalmaOperationCompleteEvent);
|
if (Context.Process.HandleTable.GenerateHandle(PalmaOperationCompleteEvent, out int Handle) == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -132,7 +132,10 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
KSession Session = new KSession(Obj, Context.Session.ServiceName);
|
KSession Session = new KSession(Obj, Context.Session.ServiceName);
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(Session);
|
if (Context.Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +149,7 @@ namespace Ryujinx.HLE.HOS.Services
|
||||||
{
|
{
|
||||||
int Handle = Context.Request.HandleDesc.ToMove[Index];
|
int Handle = Context.Request.HandleDesc.ToMove[Index];
|
||||||
|
|
||||||
KSession Session = Context.Process.HandleTable.GetData<KSession>(Handle);
|
KSession Session = Context.Process.HandleTable.GetObject<KSession>(Handle);
|
||||||
|
|
||||||
return Session?.Service is T ? (T)Session.Service : null;
|
return Session?.Service is T ? (T)Session.Service : null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Input;
|
using Ryujinx.HLE.Input;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Nfp
|
namespace Ryujinx.HLE.HOS.Services.Nfp
|
||||||
|
@ -55,7 +56,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
|
||||||
{
|
{
|
||||||
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
|
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(ActivateEvent);
|
if (Context.Process.HandleTable.GenerateHandle(ActivateEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);;
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);;
|
||||||
|
|
||||||
|
@ -66,7 +70,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
|
||||||
{
|
{
|
||||||
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
|
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(DeactivateEvent);
|
if (Context.Process.HandleTable.GenerateHandle(DeactivateEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
@ -104,7 +111,10 @@ namespace Ryujinx.HLE.HOS.Services.Nfp
|
||||||
{
|
{
|
||||||
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
|
Context.Device.Log.PrintStub(LogClass.ServiceNfp, "Stubbed.");
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(AvailabilityChangeEvent);
|
if (Context.Process.HandleTable.GenerateHandle(AvailabilityChangeEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using Ryujinx.HLE.Logging;
|
using Ryujinx.HLE.Logging;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Nifm
|
namespace Ryujinx.HLE.HOS.Services.Nifm
|
||||||
|
@ -48,8 +49,15 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
|
||||||
|
|
||||||
public long GetSystemEventReadableHandles(ServiceCtx Context)
|
public long GetSystemEventReadableHandles(ServiceCtx Context)
|
||||||
{
|
{
|
||||||
int Handle0 = Context.Process.HandleTable.OpenHandle(Event0);
|
if (Context.Process.HandleTable.GenerateHandle(Event0.ReadableEvent, out int Handle0) != KernelResult.Success)
|
||||||
int Handle1 = Context.Process.HandleTable.OpenHandle(Event1);
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Context.Process.HandleTable.GenerateHandle(Event1.ReadableEvent, out int Handle1) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle0, Handle1);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle0, Handle1);
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,10 @@ namespace Ryujinx.HLE.HOS.Services.Nv
|
||||||
int EventId = Context.RequestData.ReadInt32();
|
int EventId = Context.RequestData.ReadInt32();
|
||||||
|
|
||||||
//TODO: Use Fd/EventId, different channels have different events.
|
//TODO: Use Fd/EventId, different channels have different events.
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(Event);
|
if (Context.Process.HandleTable.GenerateHandle(Event.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
using Ryujinx.HLE.HOS.Font;
|
using Ryujinx.HLE.HOS.Font;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Pl
|
namespace Ryujinx.HLE.HOS.Services.Pl
|
||||||
|
@ -65,7 +67,10 @@ namespace Ryujinx.HLE.HOS.Services.Pl
|
||||||
{
|
{
|
||||||
Context.Device.System.Font.EnsureInitialized();
|
Context.Device.System.Font.EnsureInitialized();
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(Context.Device.System.FontSharedMem);
|
if (Context.Process.HandleTable.GenerateHandle(Context.Device.System.FontSharedMem, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
using Ryujinx.HLE.HOS.Kernel;
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Sm
|
namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
|
@ -59,7 +60,10 @@ namespace Ryujinx.HLE.HOS.Services.Sm
|
||||||
|
|
||||||
KSession Session = new KSession(ServiceFactory.MakeService(Context.Device.System, Name), Name);
|
KSession Session = new KSession(ServiceFactory.MakeService(Context.Device.System, Name), Name);
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(Session);
|
if (Context.Process.HandleTable.GenerateHandle(Session, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using ChocolArm64.Memory;
|
using ChocolArm64.Memory;
|
||||||
using Ryujinx.HLE.HOS.Ipc;
|
using Ryujinx.HLE.HOS.Ipc;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
@ -178,7 +180,10 @@ namespace Ryujinx.HLE.HOS.Services.Vi
|
||||||
{
|
{
|
||||||
string Name = GetDisplayName(Context);
|
string Name = GetDisplayName(Context);
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(Context.Device.System.VsyncEvent);
|
if (Context.Process.HandleTable.GenerateHandle(Context.Device.System.VsyncEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeCopy(Handle);
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
|
||||||
|
|
||||||
BinderEvent = new KEvent(System);
|
BinderEvent = new KEvent(System);
|
||||||
|
|
||||||
BinderEvent.Signal();
|
BinderEvent.ReadableEvent.Signal();
|
||||||
|
|
||||||
Flinger = new NvFlinger(Renderer, BinderEvent);
|
Flinger = new NvFlinger(Renderer, BinderEvent);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,10 @@ namespace Ryujinx.HLE.HOS.Services.Vi
|
||||||
int Id = Context.RequestData.ReadInt32();
|
int Id = Context.RequestData.ReadInt32();
|
||||||
uint Unk = Context.RequestData.ReadUInt32();
|
uint Unk = Context.RequestData.ReadUInt32();
|
||||||
|
|
||||||
int Handle = Context.Process.HandleTable.OpenHandle(BinderEvent);
|
if (Context.Process.HandleTable.GenerateHandle(BinderEvent.ReadableEvent, out int Handle) != KernelResult.Success)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Out of handles!");
|
||||||
|
}
|
||||||
|
|
||||||
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
|
||||||
|
|
||||||
|
|
|
@ -338,7 +338,7 @@ namespace Ryujinx.HLE.HOS.Services.Android
|
||||||
{
|
{
|
||||||
BufferQueue[Slot].State = BufferState.Free;
|
BufferQueue[Slot].State = BufferState.Free;
|
||||||
|
|
||||||
BinderEvent.Signal();
|
BinderEvent.ReadableEvent.Signal();
|
||||||
|
|
||||||
WaitBufferFree.Set();
|
WaitBufferFree.Set();
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,14 +32,14 @@ namespace Ryujinx.HLE.HOS.SystemState
|
||||||
{
|
{
|
||||||
Messages.Enqueue(Message);
|
Messages.Enqueue(Message);
|
||||||
|
|
||||||
MessageEvent.Signal();
|
MessageEvent.ReadableEvent.Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryDequeueMessage(out MessageInfo Message)
|
public bool TryDequeueMessage(out MessageInfo Message)
|
||||||
{
|
{
|
||||||
if (Messages.Count < 2)
|
if (Messages.Count < 2)
|
||||||
{
|
{
|
||||||
MessageEvent.Reset();
|
MessageEvent.ReadableEvent.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Messages.TryDequeue(out Message);
|
return Messages.TryDequeue(out Message);
|
||||||
|
|
Loading…
Reference in a new issue