diff --git a/src/SharpEmu.Libs/Np/NpAuthExports.cs b/src/SharpEmu.Libs/Np/NpAuthExports.cs index 4708074..f27ff46 100644 --- a/src/SharpEmu.Libs/Np/NpAuthExports.cs +++ b/src/SharpEmu.Libs/Np/NpAuthExports.cs @@ -13,15 +13,22 @@ public static class NpAuthExports private const int NpAuthErrorAborted = unchecked((int)0x80550304); private const int NpAuthErrorRequestMaximum = unchecked((int)0x80550305); private const int NpAuthErrorRequestNotFound = unchecked((int)0x80550306); - private const int NpAuthErrorServiceDown = unchecked((int)0x80550401); + private const int NpAuthErrorInvalidArgument = unchecked((int)0x80550301); + private const int NpErrorSignedOut = unchecked((int)0x80550006); + private const int AuthorizationCodeSize = 136; + private const int IdTokenSize = 4104; private const ulong AsyncParameterSize = 24; private static readonly ConcurrentDictionary Requests = new(); private static readonly object RequestGate = new(); private static int _nextRequestId; - private sealed class AuthRequest + private sealed class AuthRequest(bool async) { + public bool Async { get; } = async; + + public bool Completed { get; set; } + public bool Aborted { get; set; } public int Result { get; set; } @@ -47,7 +54,7 @@ public static class NpAuthExports ExportName = "sceNpAuthCreateRequest", Target = Generation.Gen5, LibraryName = "libSceNpAuth")] - public static int NpAuthCreateRequest(CpuContext ctx) => CreateRequest(ctx); + public static int NpAuthCreateRequest(CpuContext ctx) => CreateRequest(ctx, async: false); [SysAbiExport( ExportName = "sceNpAuthCreateAsyncRequest", @@ -63,7 +70,7 @@ public static class NpAuthExports return ctx.SetReturn(NpAuthErrorInvalidSize); } - return CreateRequest(ctx); + return CreateRequest(ctx, async: true); } [SysAbiExport( @@ -134,21 +141,23 @@ public static class NpAuthExports ExportName = "sceNpAuthGetAuthorizationCodeV3", Target = Generation.Gen5, LibraryName = "libSceNpAuth")] - public static int NpAuthGetAuthorizationCodeV3(CpuContext ctx) => RejectOnlineOperation(ctx); + public static int NpAuthGetAuthorizationCodeV3(CpuContext ctx) => + CompleteSignedOut(ctx, ctx[CpuRegister.Rdx], AuthorizationCodeSize, ctx[CpuRegister.Rcx]); [SysAbiExport( ExportName = "sceNpAuthGetIdTokenV3", Target = Generation.Gen5, LibraryName = "libSceNpAuth")] - public static int NpAuthGetIdTokenV3(CpuContext ctx) => RejectOnlineOperation(ctx); + public static int NpAuthGetIdTokenV3(CpuContext ctx) => + CompleteSignedOut(ctx, ctx[CpuRegister.Rdx], IdTokenSize, 0); [SysAbiExport( ExportName = "sceNpAuthGetAuthorizedAppCode", Target = Generation.Gen5, LibraryName = "libSceNpAuth")] - public static int NpAuthGetAuthorizedAppCode(CpuContext ctx) => RejectOnlineOperation(ctx); + public static int NpAuthGetAuthorizedAppCode(CpuContext ctx) => CompleteSignedOut(ctx, 0, 0, 0); - private static int CreateRequest(CpuContext ctx) + private static int CreateRequest(CpuContext ctx, bool async) { lock (RequestGate) { @@ -160,7 +169,7 @@ public static class NpAuthExports while (true) { var id = Interlocked.Increment(ref _nextRequestId); - if (Requests.TryAdd(id, new AuthRequest())) + if (Requests.TryAdd(id, new AuthRequest(async))) { return ctx.SetReturn(id); } @@ -168,8 +177,20 @@ public static class NpAuthExports } } - private static int RejectOnlineOperation(CpuContext ctx) + private static int CompleteSignedOut(CpuContext ctx, ulong outputAddress, int outputSize, ulong issuerAddress) { + if (outputAddress != 0 && outputSize != 0) + { + Span cleared = stackalloc byte[outputSize]; + cleared.Clear(); + ctx.Memory.TryWrite(outputAddress, cleared); + } + + if (issuerAddress != 0) + { + ctx.TryWriteUInt32(issuerAddress, 0); + } + if (!Requests.TryGetValue(unchecked((int)ctx[CpuRegister.Rdi]), out var request)) { return ctx.SetReturn(NpAuthErrorRequestNotFound); @@ -177,8 +198,21 @@ public static class NpAuthExports lock (request) { - request.Result = request.Aborted ? NpAuthErrorAborted : NpAuthErrorServiceDown; - return ctx.SetReturn(request.Result); + if (request.Aborted) + { + request.Result = NpAuthErrorAborted; + return ctx.SetReturn(NpAuthErrorAborted); + } + + if (request.Completed) + { + request.Result = NpAuthErrorInvalidArgument; + return ctx.SetReturn(NpAuthErrorInvalidArgument); + } + + request.Completed = true; + request.Result = NpErrorSignedOut; + return ctx.SetReturn(request.Async ? 0 : NpErrorSignedOut); } }