fix: Add ASTRO BOT compatibility stubs (#481)

* Add ASTRO BOT compatibility stubs

* Fix ASTRO BOT compatibility stubs
This commit is contained in:
Kurt Himebauch
2026-07-21 11:17:40 -04:00
committed by GitHub
parent ada67a1924
commit 4c8c67a3dd
10 changed files with 322 additions and 28 deletions
+80 -8
View File
@@ -10,6 +10,11 @@ public static class NpWebApi2Exports
private const int NpWebApi2ErrorInvalidArgument = unchecked((int)0x80553402);
private static int _initialized;
private static int _nextLibraryContextHandle;
private static int _nextPushEventHandle;
private static int _nextUserContextHandle = 1000;
private static readonly object _contextGate = new();
private static readonly HashSet<int> _libraryContexts = [];
[SysAbiExport(
Nid = "+o9816YQhqQ",
@@ -26,9 +31,10 @@ public static class NpWebApi2Exports
return ctx.SetReturn(NpWebApi2ErrorInvalidArgument);
}
var libraryContextId = CreateLibraryContextId();
Interlocked.Exchange(ref _initialized, 1);
TraceNpWebApi2("init", httpContextId, poolSize);
return ctx.SetReturn(0);
return ctx.SetReturn(libraryContextId);
}
[SysAbiExport(
@@ -38,9 +44,16 @@ public static class NpWebApi2Exports
LibraryName = "libSceNpWebApi2")]
public static int NpWebApi2InitializeAlt(CpuContext ctx)
{
var libraryContextId = unchecked((int)ctx[CpuRegister.Rdi]);
if (!IsValidLibraryContextId(libraryContextId))
{
return ctx.SetReturn(NpWebApi2ErrorInvalidArgument);
}
var handle = CreatePushEventHandle();
Interlocked.Exchange(ref _initialized, 1);
TraceNpWebApi2("init-alt", unchecked((int)ctx[CpuRegister.Rdi]), ctx[CpuRegister.Rsi]);
return ctx.SetReturn(0);
TraceNpWebApi2("init-alt", libraryContextId, 0);
return ctx.SetReturn(handle);
}
[SysAbiExport(
@@ -50,10 +63,23 @@ public static class NpWebApi2Exports
LibraryName = "libSceNpWebApi2")]
public static int NpWebApi2CreateUserContext(CpuContext ctx)
{
// No PSN backend: refuse user-context creation so the title's online
// layer backs off instead of driving a half-created context handle.
TraceNpWebApi2("create-user-context", unchecked((int)ctx[CpuRegister.Rdi]), ctx[CpuRegister.Rsi]);
return ctx.SetReturn(NpWebApi2ErrorInvalidArgument);
var libraryContextId = unchecked((int)ctx[CpuRegister.Rdi]);
var userId = unchecked((int)ctx[CpuRegister.Rsi]);
TraceNpWebApi2(
"create-user-context",
libraryContextId,
unchecked((uint)userId));
if (Volatile.Read(ref _initialized) == 0 ||
!IsValidLibraryContextId(libraryContextId) ||
userId == -1)
{
return ctx.SetReturn(NpWebApi2ErrorInvalidArgument);
}
var userContextId = Interlocked.Increment(ref _nextUserContextHandle);
return ctx.SetReturn(userContextId);
}
[SysAbiExport(
@@ -64,11 +90,57 @@ public static class NpWebApi2Exports
public static int NpWebApi2Terminate(CpuContext ctx)
{
var libraryContextId = unchecked((int)ctx[CpuRegister.Rdi]);
Interlocked.Exchange(ref _initialized, 0);
if (!IsValidLibraryContextId(libraryContextId))
{
return ctx.SetReturn(NpWebApi2ErrorInvalidArgument);
}
RemoveLibraryContextId(libraryContextId);
TraceNpWebApi2("term", libraryContextId, 0);
return ctx.SetReturn(0);
}
private static int CreateLibraryContextId()
{
var handle = Interlocked.Increment(ref _nextLibraryContextHandle);
lock (_contextGate)
{
_libraryContexts.Add(handle);
}
return handle;
}
private static int CreatePushEventHandle()
{
return Interlocked.Increment(ref _nextPushEventHandle);
}
private static bool IsValidLibraryContextId(int libraryContextId)
{
if (libraryContextId <= 0 || libraryContextId >= 0x8000)
{
return false;
}
lock (_contextGate)
{
return _libraryContexts.Contains(libraryContextId);
}
}
private static void RemoveLibraryContextId(int libraryContextId)
{
lock (_contextGate)
{
_libraryContexts.Remove(libraryContextId);
if (_libraryContexts.Count == 0)
{
Interlocked.Exchange(ref _initialized, 0);
}
}
}
private static void TraceNpWebApi2(string operation, int id, ulong arg0)
{
if (!string.Equals(Environment.GetEnvironmentVariable("SHARPEMU_LOG_NP_WEB_API2"), "1", StringComparison.Ordinal))