Compare commits

...

4 Commits

Author SHA1 Message Date
df70442c46 InstEmitMemoryEx: Barrier after write on ordered store (#3193)
* InstEmitMemoryEx: Barrier after write on ordered store

* increment ptc version

* 32
2022-03-19 10:32:35 -03:00
e2ffa5a125 ntc: Implement IEnsureNetworkClockAvailabilityService (#3192)
* ntc: Implement IEnsureNetworkClockAvailabilityService

This PR implement a basic `IEnsureNetworkClockAvailabilityService` checked by RE. It's needed by Splatoon 2 with Guest Internet Access enabled. Game is now playable with this setting.

* Update Ryujinx.HLE/HOS/Services/Nim/Ntc/StaticService/IEnsureNetworkClockAvailabilityService.cs

Co-authored-by: gdkchan <gab.dark.100@gmail.com>

Co-authored-by: gdkchan <gab.dark.100@gmail.com>
2022-03-15 04:07:07 +01:00
73feac5819 Caching local network info and using an event handler to invalidate as needed (improves menu slow down issue in FE3H) (#2761)
* Update IGeneralService.cs

Fix IPV4 local ip related frame drop in fire emblem by rewriting [CommandHipc(12)]

* Fix IPV4 Local IP Slowdown & Style Fixes

fix a missing space

* Remove unnecessary line

* Fix for hardcoding which index to use

* Replace argument with empty string.

By sending an empty string to Dns.GetHostAddresses("") you get back localhost info only.

* Add caching, undo change in GetCurrentIpAddress

Implement caching and revert the GetCurrentIP() function, speed improvements still present.

* Remove unnecessary using

* Syntax fixes and removing extra lines

Requested changes by AcK77

* Properly unsubscribe from event handler

Adds an unsubscribe in the dispose section of IGeneralService
2022-03-15 03:49:35 +01:00
e5ad1dfa48 Implement S8D24 texture format and tweak depth range detection (#2458) 2022-03-15 03:42:08 +01:00
18 changed files with 343 additions and 53 deletions

View File

@ -130,11 +130,6 @@ namespace ARMeilleure.Instructions
bool ordered = (accType & AccessType.Ordered) != 0;
bool exclusive = (accType & AccessType.Exclusive) != 0;
if (ordered)
{
EmitBarrier(context);
}
Operand address = context.Copy(GetIntOrSP(context, op.Rn));
Operand t = GetIntOrZR(context, op.Rt);
@ -163,6 +158,11 @@ namespace ARMeilleure.Instructions
{
EmitStoreExclusive(context, address, t, exclusive, op.Size, op.Rs, a32: false);
}
if (ordered)
{
EmitBarrier(context);
}
}
private static void EmitBarrier(ArmEmitterContext context)

View File

@ -146,13 +146,13 @@ namespace ARMeilleure.Instructions
var exclusive = (accType & AccessType.Exclusive) != 0;
var ordered = (accType & AccessType.Ordered) != 0;
if (ordered)
{
EmitBarrier(context);
}
if ((accType & AccessType.Load) != 0)
{
if (ordered)
{
EmitBarrier(context);
}
if (size == DWordSizeLog2)
{
// Keep loads atomic - make the call to get the whole region and then decompose it into parts
@ -219,6 +219,11 @@ namespace ARMeilleure.Instructions
Operand value = context.ZeroExtend32(OperandType.I64, GetIntA32(context, op.Rt));
EmitStoreExclusive(context, address, value, exclusive, size, op.Rd, a32: true);
}
if (ordered)
{
EmitBarrier(context);
}
}
}

View File

@ -27,7 +27,7 @@ namespace ARMeilleure.Translation.PTC
private const string OuterHeaderMagicString = "PTCohd\0\0";
private const string InnerHeaderMagicString = "PTCihd\0\0";
private const uint InternalVersion = 3179; //! To be incremented manually for each change to the ARMeilleure project.
private const uint InternalVersion = 3193; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";

View File

@ -47,6 +47,7 @@ namespace Ryujinx.Common.Logging
ServiceNim,
ServiceNs,
ServiceNsd,
ServiceNtc,
ServiceNv,
ServiceOlsc,
ServicePctl,

View File

@ -52,7 +52,7 @@ namespace Ryujinx.Graphics.GAL
R32G32B32A32Sint,
S8Uint,
D16Unorm,
D24X8Unorm,
S8UintD24Unorm,
D32Float,
D24UnormS8Uint,
D32FloatS8Uint,
@ -266,7 +266,7 @@ namespace Ryujinx.Graphics.GAL
{
case Format.D16Unorm:
case Format.D24UnormS8Uint:
case Format.D24X8Unorm:
case Format.S8UintD24Unorm:
case Format.D32Float:
case Format.D32FloatS8Uint:
case Format.S8Uint:

View File

@ -28,13 +28,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Types
{
return format switch
{
ZetaFormat.D32Float => new FormatInfo(Format.D32Float, 1, 1, 4, 1),
ZetaFormat.D16Unorm => new FormatInfo(Format.D16Unorm, 1, 1, 2, 1),
ZetaFormat.D24UnormS8Uint => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
ZetaFormat.D24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 1),
ZetaFormat.S8UintD24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
ZetaFormat.S8Uint => new FormatInfo(Format.S8Uint, 1, 1, 1, 1),
ZetaFormat.D32FloatS8Uint => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2),
ZetaFormat.D32Float => new FormatInfo(Format.D32Float, 1, 1, 4, 1),
ZetaFormat.D16Unorm => new FormatInfo(Format.D16Unorm, 1, 1, 2, 1),
ZetaFormat.D24UnormS8Uint => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2),
ZetaFormat.D24Unorm => new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 1),
ZetaFormat.S8UintD24Unorm => new FormatInfo(Format.S8UintD24Unorm, 1, 1, 4, 2),
ZetaFormat.S8Uint => new FormatInfo(Format.S8Uint, 1, 1, 1, 1),
ZetaFormat.D32FloatS8Uint => new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2),
_ => FormatInfo.Default
};
}

View File

@ -55,6 +55,7 @@ namespace Ryujinx.Graphics.Gpu.Image
{ 0x24a0e, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2) },
{ 0x24a29, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2) },
{ 0x48a29, new FormatInfo(Format.D24UnormS8Uint, 1, 1, 4, 2) },
{ 0x4912b, new FormatInfo(Format.S8UintD24Unorm, 1, 1, 4, 2) },
{ 0x25385, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
{ 0x253b0, new FormatInfo(Format.D32FloatS8Uint, 1, 1, 8, 2) },
{ 0xa4908, new FormatInfo(Format.R8G8B8A8Srgb, 1, 1, 4, 4) },

View File

@ -203,7 +203,7 @@ namespace Ryujinx.Graphics.Gpu.Image
}
if ((lhs.FormatInfo.Format == Format.D24UnormS8Uint ||
lhs.FormatInfo.Format == Format.D24X8Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
lhs.FormatInfo.Format == Format.S8UintD24Unorm) && rhs.FormatInfo.Format == Format.B8G8R8A8Unorm)
{
return TextureMatchQuality.FormatAlias;
}

View File

@ -362,7 +362,7 @@ namespace Ryujinx.Graphics.Gpu.Image
return DepthStencilMode.Depth;
}
if (format == Format.D24X8Unorm || format == Format.D24UnormS8Uint)
if (format == Format.D24UnormS8Uint)
{
return component == SwizzleComponent.Red
? DepthStencilMode.Stencil

View File

@ -6,15 +6,15 @@ namespace Ryujinx.Graphics.OpenGL
{
struct FormatTable
{
private static FormatInfo[] Table;
private static SizedInternalFormat[] TableImage;
private static FormatInfo[] _table;
private static SizedInternalFormat[] _tableImage;
static FormatTable()
{
int tableSize = Enum.GetNames<Format>().Length;
Table = new FormatInfo[tableSize];
TableImage = new SizedInternalFormat[tableSize];
_table = new FormatInfo[tableSize];
_tableImage = new SizedInternalFormat[tableSize];
Add(Format.R8Unorm, new FormatInfo(1, true, false, All.R8, PixelFormat.Red, PixelType.UnsignedByte));
Add(Format.R8Snorm, new FormatInfo(1, true, false, All.R8Snorm, PixelFormat.Red, PixelType.Byte));
@ -66,7 +66,7 @@ namespace Ryujinx.Graphics.OpenGL
Add(Format.R32G32B32A32Sint, new FormatInfo(4, false, false, All.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int));
Add(Format.S8Uint, new FormatInfo(1, false, false, All.StencilIndex8, PixelFormat.StencilIndex, PixelType.UnsignedByte));
Add(Format.D16Unorm, new FormatInfo(1, false, false, All.DepthComponent16, PixelFormat.DepthComponent, PixelType.UnsignedShort));
Add(Format.D24X8Unorm, new FormatInfo(1, false, false, All.DepthComponent24, PixelFormat.DepthComponent, PixelType.UnsignedInt));
Add(Format.S8UintD24Unorm, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
Add(Format.D32Float, new FormatInfo(1, false, false, All.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float));
Add(Format.D24UnormS8Uint, new FormatInfo(1, false, false, All.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248));
Add(Format.D32FloatS8Uint, new FormatInfo(1, false, false, All.Depth32fStencil8, PixelFormat.DepthStencil, PixelType.Float32UnsignedInt248Rev));
@ -218,22 +218,22 @@ namespace Ryujinx.Graphics.OpenGL
private static void Add(Format format, FormatInfo info)
{
Table[(int)format] = info;
_table[(int)format] = info;
}
private static void Add(Format format, SizedInternalFormat sif)
{
TableImage[(int)format] = sif;
_tableImage[(int)format] = sif;
}
public static FormatInfo GetFormatInfo(Format format)
{
return Table[(int)format];
return _table[(int)format];
}
public static SizedInternalFormat GetImageFormat(Format format)
{
return TableImage[(int)format];
return _tableImage[(int)format];
}
}
}

View File

@ -127,14 +127,13 @@ namespace Ryujinx.Graphics.OpenGL
private static bool IsPackedDepthStencilFormat(Format format)
{
return format == Format.D24UnormS8Uint ||
format == Format.D32FloatS8Uint;
format == Format.D32FloatS8Uint ||
format == Format.S8UintD24Unorm;
}
private static bool IsDepthOnlyFormat(Format format)
{
return format == Format.D16Unorm ||
format == Format.D24X8Unorm ||
format == Format.D32Float;
return format == Format.D16Unorm || format == Format.D32Float;
}
public void Dispose()

View File

@ -0,0 +1,149 @@
using System;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;
namespace Ryujinx.Graphics.OpenGL.Image
{
static class FormatConverter
{
public unsafe static byte[] ConvertS8D24ToD24S8(ReadOnlySpan<byte> data)
{
byte[] output = new byte[data.Length];
int start = 0;
if (Avx2.IsSupported)
{
var mask = Vector256.Create(
(byte)3, (byte)0, (byte)1, (byte)2,
(byte)7, (byte)4, (byte)5, (byte)6,
(byte)11, (byte)8, (byte)9, (byte)10,
(byte)15, (byte)12, (byte)13, (byte)14,
(byte)19, (byte)16, (byte)17, (byte)18,
(byte)23, (byte)20, (byte)21, (byte)22,
(byte)27, (byte)24, (byte)25, (byte)26,
(byte)31, (byte)28, (byte)29, (byte)30);
int sizeAligned = data.Length & ~31;
fixed (byte* pInput = data, pOutput = output)
{
for (uint i = 0; i < sizeAligned; i += 32)
{
var dataVec = Avx.LoadVector256(pInput + i);
dataVec = Avx2.Shuffle(dataVec, mask);
Avx.Store(pOutput + i, dataVec);
}
}
start = sizeAligned;
}
else if (Ssse3.IsSupported)
{
var mask = Vector128.Create(
(byte)3, (byte)0, (byte)1, (byte)2,
(byte)7, (byte)4, (byte)5, (byte)6,
(byte)11, (byte)8, (byte)9, (byte)10,
(byte)15, (byte)12, (byte)13, (byte)14);
int sizeAligned = data.Length & ~15;
fixed (byte* pInput = data, pOutput = output)
{
for (uint i = 0; i < sizeAligned; i += 16)
{
var dataVec = Sse2.LoadVector128(pInput + i);
dataVec = Ssse3.Shuffle(dataVec, mask);
Sse2.Store(pOutput + i, dataVec);
}
}
start = sizeAligned;
}
var outSpan = MemoryMarshal.Cast<byte, uint>(output);
var dataSpan = MemoryMarshal.Cast<byte, uint>(data);
for (int i = start / sizeof(uint); i < dataSpan.Length; i++)
{
outSpan[i] = BitOperations.RotateLeft(dataSpan[i], 8);
}
return output;
}
public unsafe static byte[] ConvertD24S8ToS8D24(ReadOnlySpan<byte> data)
{
byte[] output = new byte[data.Length];
int start = 0;
if (Avx2.IsSupported)
{
var mask = Vector256.Create(
(byte)1, (byte)2, (byte)3, (byte)0,
(byte)5, (byte)6, (byte)7, (byte)4,
(byte)9, (byte)10, (byte)11, (byte)8,
(byte)13, (byte)14, (byte)15, (byte)12,
(byte)17, (byte)18, (byte)19, (byte)16,
(byte)21, (byte)22, (byte)23, (byte)20,
(byte)25, (byte)26, (byte)27, (byte)24,
(byte)29, (byte)30, (byte)31, (byte)28);
int sizeAligned = data.Length & ~31;
fixed (byte* pInput = data, pOutput = output)
{
for (uint i = 0; i < sizeAligned; i += 32)
{
var dataVec = Avx.LoadVector256(pInput + i);
dataVec = Avx2.Shuffle(dataVec, mask);
Avx.Store(pOutput + i, dataVec);
}
}
start = sizeAligned;
}
else if (Ssse3.IsSupported)
{
var mask = Vector128.Create(
(byte)1, (byte)2, (byte)3, (byte)0,
(byte)5, (byte)6, (byte)7, (byte)4,
(byte)9, (byte)10, (byte)11, (byte)8,
(byte)13, (byte)14, (byte)15, (byte)12);
int sizeAligned = data.Length & ~15;
fixed (byte* pInput = data, pOutput = output)
{
for (uint i = 0; i < sizeAligned; i += 16)
{
var dataVec = Sse2.LoadVector128(pInput + i);
dataVec = Ssse3.Shuffle(dataVec, mask);
Sse2.Store(pOutput + i, dataVec);
}
}
start = sizeAligned;
}
var outSpan = MemoryMarshal.Cast<byte, uint>(output);
var dataSpan = MemoryMarshal.Cast<byte, uint>(data);
for (int i = start / sizeof(uint); i < dataSpan.Length; i++)
{
outSpan[i] = BitOperations.RotateRight(dataSpan[i], 8);
}
return output;
}
}
}

View File

@ -291,7 +291,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
private static ClearBufferMask GetMask(Format format)
{
if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint)
if (format == Format.D24UnormS8Uint || format == Format.D32FloatS8Uint || format == Format.S8UintD24Unorm)
{
return ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit;
}
@ -311,9 +311,7 @@ namespace Ryujinx.Graphics.OpenGL.Image
private static bool IsDepthOnly(Format format)
{
return format == Format.D16Unorm ||
format == Format.D24X8Unorm ||
format == Format.D32Float;
return format == Format.D16Unorm || format == Format.D32Float;
}
public TextureView BgraSwap(TextureView from)

View File

@ -140,9 +140,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
size += Info.GetMipSize(level);
}
ReadOnlySpan<byte> data;
if (HwCapabilities.UsePersistentBufferForFlush)
{
return _renderer.PersistentBuffers.Default.GetTextureData(this, size);
data = _renderer.PersistentBuffers.Default.GetTextureData(this, size);
}
else
{
@ -150,8 +152,15 @@ namespace Ryujinx.Graphics.OpenGL.Image
WriteTo(target);
return new ReadOnlySpan<byte>(target.ToPointer(), size);
data = new ReadOnlySpan<byte>(target.ToPointer(), size);
}
if (Format == Format.S8UintD24Unorm)
{
data = FormatConverter.ConvertD24S8ToS8D24(data);
}
return data;
}
public unsafe ReadOnlySpan<byte> GetData(int layer, int level)
@ -285,6 +294,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
public void SetData(ReadOnlySpan<byte> data)
{
if (Format == Format.S8UintD24Unorm)
{
data = FormatConverter.ConvertS8D24ToD24S8(data);
}
unsafe
{
fixed (byte* ptr = data)
@ -296,6 +310,11 @@ namespace Ryujinx.Graphics.OpenGL.Image
public void SetData(ReadOnlySpan<byte> data, int layer, int level)
{
if (Format == Format.S8UintD24Unorm)
{
data = FormatConverter.ConvertS8D24ToD24S8(data);
}
unsafe
{
fixed (byte* ptr = data)

View File

@ -14,6 +14,9 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
{
private GeneralServiceDetail _generalServiceDetail;
private IPInterfaceProperties _targetPropertiesCache = null;
private UnicastIPAddressInformation _targetAddressInfoCache = null;
public IGeneralService()
{
_generalServiceDetail = new GeneralServiceDetail
@ -22,6 +25,8 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
IsAnyInternetRequestAccepted = true // NOTE: Why not accept any internet request?
};
NetworkChange.NetworkAddressChanged += new NetworkAddressChangedEventHandler(LocalInterfaceCacheHandler);
GeneralServiceManager.Add(_generalServiceDetail);
}
@ -165,6 +170,11 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
return (null, null);
}
if (_targetPropertiesCache != null && _targetAddressInfoCache != null)
{
return (_targetPropertiesCache, _targetAddressInfoCache);
}
IPInterfaceProperties targetProperties = null;
UnicastIPAddressInformation targetAddressInfo = null;
@ -194,13 +204,26 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
}
}
_targetPropertiesCache = targetProperties;
_targetAddressInfoCache = targetAddressInfo;
return (targetProperties, targetAddressInfo);
}
private void LocalInterfaceCacheHandler(object sender, EventArgs e)
{
Logger.Info?.Print(LogClass.ServiceNifm, $"NetworkAddress changed, invalidating cached data.");
_targetPropertiesCache = null;
_targetAddressInfoCache = null;
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
NetworkChange.NetworkAddressChanged -= LocalInterfaceCacheHandler;
GeneralServiceManager.Remove(_generalServiceDetail.ClientId);
}
}

View File

@ -1,8 +1,24 @@
namespace Ryujinx.HLE.HOS.Services.Nim.Ntc
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService;
namespace Ryujinx.HLE.HOS.Services.Nim.Ntc
{
[Service("ntc")]
class IStaticService : IpcService
{
public IStaticService(ServiceCtx context) { }
[CommandHipc(0)]
// OpenEnsureNetworkClockAvailabilityService(u64) -> object<nn::ntc::detail::service::IEnsureNetworkClockAvailabilityService>
public ResultCode CreateAsyncInterface(ServiceCtx context)
{
ulong unknown = context.RequestData.ReadUInt64();
MakeObject(context, new IEnsureNetworkClockAvailabilityService(context));
Logger.Stub?.PrintStub(LogClass.ServiceNtc, new { unknown });
return ResultCode.Success;
}
}
}

View File

@ -0,0 +1,77 @@
using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.Kernel.Common;
using Ryujinx.HLE.HOS.Kernel.Threading;
using System;
namespace Ryujinx.HLE.HOS.Services.Nim.Ntc.StaticService
{
class IEnsureNetworkClockAvailabilityService : IpcService
{
private KEvent _finishNotificationEvent;
private ResultCode _taskResultCode;
public IEnsureNetworkClockAvailabilityService(ServiceCtx context)
{
_finishNotificationEvent = new KEvent(context.Device.System.KernelContext);
_taskResultCode = ResultCode.Success;
// NOTE: The service starts a thread that polls Nintendo NTP server and syncs the time with it.
// Additionnally it gets and uses some settings too:
// autonomic_correction_interval_seconds, autonomic_correction_failed_retry_interval_seconds,
// autonomic_correction_immediate_try_count_max, autonomic_correction_immediate_try_interval_milliseconds
}
[CommandHipc(0)]
// StartTask()
public ResultCode StartTask(ServiceCtx context)
{
if (!context.Device.Configuration.EnableInternetAccess)
{
return (ResultCode)Time.ResultCode.NetworkTimeNotAvailable;
}
// NOTE: Since we don't support the Nintendo NTP server, we can signal the event now to confirm the update task is done.
_finishNotificationEvent.ReadableEvent.Signal();
Logger.Stub?.PrintStub(LogClass.ServiceNtc);
return ResultCode.Success;
}
[CommandHipc(1)]
// GetFinishNotificationEvent() -> handle<copy>
public ResultCode GetFinishNotificationEvent(ServiceCtx context)
{
if (context.Process.HandleTable.GenerateHandle(_finishNotificationEvent.ReadableEvent, out int finishNotificationEventHandle) != KernelResult.Success)
{
throw new InvalidOperationException("Out of handles!");
}
context.Response.HandleDesc = IpcHandleDesc.MakeCopy(finishNotificationEventHandle);
return ResultCode.Success;
}
[CommandHipc(2)]
// GetResult()
public ResultCode GetResult(ServiceCtx context)
{
return _taskResultCode;
}
[CommandHipc(3)]
// Cancel()
public ResultCode Cancel(ServiceCtx context)
{
// NOTE: The update task should be canceled here.
_finishNotificationEvent.ReadableEvent.Signal();
_taskResultCode = (ResultCode)Time.ResultCode.NetworkTimeTaskCanceled;
Logger.Stub?.PrintStub(LogClass.ServiceNtc);
return ResultCode.Success;
}
}
}

View File

@ -7,16 +7,18 @@
Success = 0,
TimeServiceNotInitialized = (0 << ErrorCodeShift) | ModuleId,
PermissionDenied = (1 << ErrorCodeShift) | ModuleId,
TimeMismatch = (102 << ErrorCodeShift) | ModuleId,
UninitializedClock = (103 << ErrorCodeShift) | ModuleId,
TimeNotFound = (200 << ErrorCodeShift) | ModuleId,
Overflow = (201 << ErrorCodeShift) | ModuleId,
LocationNameTooLong = (801 << ErrorCodeShift) | ModuleId,
OutOfRange = (902 << ErrorCodeShift) | ModuleId,
TimeZoneConversionFailed = (903 << ErrorCodeShift) | ModuleId,
TimeZoneNotFound = (989 << ErrorCodeShift) | ModuleId,
NotImplemented = (990 << ErrorCodeShift) | ModuleId,
TimeServiceNotInitialized = (0 << ErrorCodeShift) | ModuleId,
PermissionDenied = (1 << ErrorCodeShift) | ModuleId,
TimeMismatch = (102 << ErrorCodeShift) | ModuleId,
UninitializedClock = (103 << ErrorCodeShift) | ModuleId,
TimeNotFound = (200 << ErrorCodeShift) | ModuleId,
Overflow = (201 << ErrorCodeShift) | ModuleId,
LocationNameTooLong = (801 << ErrorCodeShift) | ModuleId,
OutOfRange = (902 << ErrorCodeShift) | ModuleId,
TimeZoneConversionFailed = (903 << ErrorCodeShift) | ModuleId,
TimeZoneNotFound = (989 << ErrorCodeShift) | ModuleId,
NotImplemented = (990 << ErrorCodeShift) | ModuleId,
NetworkTimeNotAvailable = (1000 << ErrorCodeShift) | ModuleId,
NetworkTimeTaskCanceled = (1003 << ErrorCodeShift) | ModuleId,
}
}