Accurately implement time shared memory operations
This commit is contained in:
parent
0fa8f92cde
commit
45125f0e3a
4 changed files with 95 additions and 9 deletions
|
@ -59,6 +59,11 @@ namespace Ryujinx.HLE
|
||||||
return *((ulong*)(_ramPtr + position));
|
return *((ulong*)(_ramPtr + position));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public unsafe T ReadStruct<T>(long position)
|
||||||
|
{
|
||||||
|
return Marshal.PtrToStructure<T>((IntPtr)(_ramPtr + position));
|
||||||
|
}
|
||||||
|
|
||||||
public void WriteSByte(long position, sbyte value)
|
public void WriteSByte(long position, sbyte value)
|
||||||
{
|
{
|
||||||
WriteByte(position, (byte)value);
|
WriteByte(position, (byte)value);
|
||||||
|
|
|
@ -73,7 +73,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
|
||||||
TimeSpanType currentTimePoint = StandardSteadyClock.GetCurrentRawTimePoint(thread);
|
TimeSpanType currentTimePoint = StandardSteadyClock.GetCurrentRawTimePoint(thread);
|
||||||
|
|
||||||
SharedMemory.SetupStandardSteadyClock(clockSourceId, currentTimePoint);
|
SharedMemory.SetupStandardSteadyClock(thread, clockSourceId, currentTimePoint);
|
||||||
|
|
||||||
// TODO: propagate IPC late binding of "time:s" and "time:p"
|
// TODO: propagate IPC late binding of "time:s" and "time:p"
|
||||||
return ResultCode.Success;
|
return ResultCode.Success;
|
||||||
|
@ -174,7 +174,7 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
|
||||||
TimeSpanType currentTimePoint = StandardSteadyClock.GetCurrentRawTimePoint(thread);
|
TimeSpanType currentTimePoint = StandardSteadyClock.GetCurrentRawTimePoint(thread);
|
||||||
|
|
||||||
SharedMemory.SetSteadyClockRawTimePoint(currentTimePoint);
|
SharedMemory.SetSteadyClockRawTimePoint(thread, currentTimePoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Threading;
|
||||||
using Ryujinx.HLE.HOS.Kernel.Memory;
|
using Ryujinx.HLE.HOS.Kernel.Memory;
|
||||||
|
using Ryujinx.HLE.HOS.Kernel.Threading;
|
||||||
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
using Ryujinx.HLE.HOS.Services.Time.Clock;
|
||||||
|
using Ryujinx.HLE.HOS.Services.Time.Types;
|
||||||
using Ryujinx.HLE.Utilities;
|
using Ryujinx.HLE.Utilities;
|
||||||
|
|
||||||
namespace Ryujinx.HLE.HOS.Services.Time
|
namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
|
@ -12,6 +16,11 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
private long _timeSharedMemoryAddress;
|
private long _timeSharedMemoryAddress;
|
||||||
private int _timeSharedMemorySize;
|
private int _timeSharedMemorySize;
|
||||||
|
|
||||||
|
private const uint SteadyClockContextOffset = 0x00;
|
||||||
|
private const uint LocalSystemClockContextOffset = 0x38;
|
||||||
|
private const uint NetworkSystemClockContextOffset = 0x80;
|
||||||
|
private const uint AutomaticCorrectionEnabledOffset = 0xC8;
|
||||||
|
|
||||||
public void Initialize(Switch device, KSharedMemory sharedMemory, long timeSharedMemoryAddress, int timeSharedMemorySize)
|
public void Initialize(Switch device, KSharedMemory sharedMemory, long timeSharedMemoryAddress, int timeSharedMemorySize)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
|
@ -28,29 +37,89 @@ namespace Ryujinx.HLE.HOS.Services.Time
|
||||||
return _sharedMemory;
|
return _sharedMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetupStandardSteadyClock(UInt128 clockSourceId, TimeSpanType currentTimePoint)
|
public void SetupStandardSteadyClock(KThread thread, UInt128 clockSourceId, TimeSpanType currentTimePoint)
|
||||||
{
|
{
|
||||||
// TODO
|
TimeSpanType ticksTimeSpan;
|
||||||
|
|
||||||
|
// As this may be called before the guest code, we support passing a null thread to make this api usable.
|
||||||
|
if (thread == null)
|
||||||
|
{
|
||||||
|
ticksTimeSpan = TimeSpanType.FromSeconds(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.CntpctEl0, thread.Context.CntfrqEl0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SteadyClockContext context = new SteadyClockContext
|
||||||
|
{
|
||||||
|
InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds),
|
||||||
|
ClockSourceId = clockSourceId
|
||||||
|
};
|
||||||
|
|
||||||
|
WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetAutomaticCorrectionEnabled(bool isAutomaticCorrectionEnabled)
|
public void SetAutomaticCorrectionEnabled(bool isAutomaticCorrectionEnabled)
|
||||||
{
|
{
|
||||||
// TODO
|
// We convert the bool to byte here as a bool in C# takes 4 bytes...
|
||||||
|
WriteObjectToSharedMemory(AutomaticCorrectionEnabledOffset, 0, Convert.ToByte(isAutomaticCorrectionEnabled));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetSteadyClockRawTimePoint(TimeSpanType currentTimePoint)
|
public void SetSteadyClockRawTimePoint(KThread thread, TimeSpanType currentTimePoint)
|
||||||
{
|
{
|
||||||
// TODO
|
SteadyClockContext context = ReadObjectFromSharedMemory<SteadyClockContext>(SteadyClockContextOffset, 4);
|
||||||
|
TimeSpanType ticksTimeSpan = TimeSpanType.FromTicks(thread.Context.CntpctEl0, thread.Context.CntfrqEl0);
|
||||||
|
|
||||||
|
context.InternalOffset = (ulong)(currentTimePoint.NanoSeconds - ticksTimeSpan.NanoSeconds);
|
||||||
|
|
||||||
|
WriteObjectToSharedMemory(SteadyClockContextOffset, 4, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateLocalSystemClockContext(SystemClockContext context)
|
public void UpdateLocalSystemClockContext(SystemClockContext context)
|
||||||
{
|
{
|
||||||
// TODO
|
WriteObjectToSharedMemory(LocalSystemClockContextOffset, 4, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateNetworkSystemClockContext(SystemClockContext context)
|
public void UpdateNetworkSystemClockContext(SystemClockContext context)
|
||||||
{
|
{
|
||||||
// TODO
|
WriteObjectToSharedMemory(NetworkSystemClockContextOffset, 4, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private T ReadObjectFromSharedMemory<T>(long offset, long padding)
|
||||||
|
{
|
||||||
|
long indexOffset = _timeSharedMemoryAddress + offset;
|
||||||
|
|
||||||
|
T result;
|
||||||
|
uint index;
|
||||||
|
uint possiblyNewIndex;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
index = _device.Memory.ReadUInt32(indexOffset);
|
||||||
|
|
||||||
|
long objectOffset = indexOffset + 4 + padding + (index & 1) * Marshal.SizeOf<T>();
|
||||||
|
|
||||||
|
result = _device.Memory.ReadStruct<T>(objectOffset);
|
||||||
|
Thread.MemoryBarrier();
|
||||||
|
|
||||||
|
possiblyNewIndex = _device.Memory.ReadUInt32(indexOffset);
|
||||||
|
} while (index != possiblyNewIndex);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteObjectToSharedMemory<T>(long offset, long padding, T value)
|
||||||
|
{
|
||||||
|
long indexOffset = _timeSharedMemoryAddress + offset;
|
||||||
|
uint newIndex = _device.Memory.ReadUInt32(indexOffset) + 1;
|
||||||
|
long objectOffset = indexOffset + 4 + padding + (newIndex & 1) * Marshal.SizeOf<T>();
|
||||||
|
|
||||||
|
_device.Memory.WriteStruct(objectOffset, value);
|
||||||
|
|
||||||
|
Thread.MemoryBarrier();
|
||||||
|
|
||||||
|
_device.Memory.WriteUInt32(indexOffset, newIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
Ryujinx.HLE/HOS/Services/Time/Types/SteadyClockContext.cs
Normal file
12
Ryujinx.HLE/HOS/Services/Time/Types/SteadyClockContext.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Ryujinx.HLE.Utilities;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace Ryujinx.HLE.HOS.Services.Time.Types
|
||||||
|
{
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
struct SteadyClockContext
|
||||||
|
{
|
||||||
|
public ulong InternalOffset;
|
||||||
|
public UInt128 ClockSourceId;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue