From 181286f6212105ba34790e7d1732b4b2e4a2eabf Mon Sep 17 00:00:00 2001 From: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com> Date: Sun, 19 Jul 2026 14:01:25 +0200 Subject: [PATCH] [Libs] Implement sceAgcGetIsTrinityMode, NpReachability and Trophy2 info Three exports DOOM + DOOM II (PPSA21444) imports and currently receives unresolved-stub errors for. sceAgcGetIsTrinityMode reports the base console this backend emulates. It returns the flag in rax and writes no guest memory: the observed rdi at the call site sits inside the AGC state block, immediately below the shader handles the guest stores, so writing through it would corrupt live state if that register is stale rather than an out-pointer. sceNpRegisterNpReachabilityStateCallback accepts the callback and never fires it, matching the existing sceNpRegisterStateCallback handling. Reachability transitions only occur on a live PSN connection. sceNpTrophy2GetTrophyInfo reports NOT_FOUND rather than success. Succeeding requires filling SceNpTrophy2Details and SceNpTrophy2Data, whose layouts are not confirmed here, and a title trusting zeroed details would read an empty name and grade 0 as real data. NOT_FOUND is a documented outcome callers already handle. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/SharpEmu.Libs/Agc/AgcExports.cs | 15 +++++++++++++++ src/SharpEmu.Libs/Np/NpManagerExports.cs | 17 +++++++++++++++++ src/SharpEmu.Libs/Np/NpTrophy2Exports.cs | 19 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/src/SharpEmu.Libs/Agc/AgcExports.cs b/src/SharpEmu.Libs/Agc/AgcExports.cs index a79a1e26..e55e21c9 100644 --- a/src/SharpEmu.Libs/Agc/AgcExports.cs +++ b/src/SharpEmu.Libs/Agc/AgcExports.cs @@ -640,6 +640,21 @@ public static partial class AgcExports public static int GetRegisterDefaults2Internal(CpuContext ctx) => ReturnRegisterDefaults(ctx, internalDefaults: true); + /// + /// Reports that the GPU is not running in Trinity mode, matching the base + /// console this backend emulates. + /// + [SysAbiExport( + Nid = "BfBDZGbti7A", + ExportName = "sceAgcGetIsTrinityMode", + Target = Generation.Gen5, + LibraryName = "libSceAgc")] + public static int GetIsTrinityMode(CpuContext ctx) + { + ctx[CpuRegister.Rax] = 0; + return (int)OrbisGen2Result.ORBIS_GEN2_OK; + } + [SysAbiExport( Nid = "f3dg2CSgRKY", ExportName = "sceAgcCreateShader", diff --git a/src/SharpEmu.Libs/Np/NpManagerExports.cs b/src/SharpEmu.Libs/Np/NpManagerExports.cs index e5d44fe2..1247683b 100644 --- a/src/SharpEmu.Libs/Np/NpManagerExports.cs +++ b/src/SharpEmu.Libs/Np/NpManagerExports.cs @@ -69,6 +69,23 @@ public static class NpManagerExports return (int)OrbisGen2Result.ORBIS_GEN2_OK; } + /// + /// Accepts the reachability callback and never invokes it. Reachability + /// transitions only ever fire on a real PSN connection, which an offline + /// session does not have, so registering successfully and staying silent is + /// the accurate emulation of a signed-out console rather than a stub. + /// + [SysAbiExport( + Nid = "hw5KNqAAels", + ExportName = "sceNpRegisterNpReachabilityStateCallback", + Target = Generation.Gen4 | Generation.Gen5, + LibraryName = "libSceNpManager")] + public static int NpRegisterNpReachabilityStateCallback(CpuContext ctx) + { + ctx[CpuRegister.Rax] = 0; + return (int)OrbisGen2Result.ORBIS_GEN2_OK; + } + [SysAbiExport( Nid = "qQJfO8HAiaY", ExportName = "sceNpRegisterStateCallbackA", diff --git a/src/SharpEmu.Libs/Np/NpTrophy2Exports.cs b/src/SharpEmu.Libs/Np/NpTrophy2Exports.cs index 4a978dbf..c636d62d 100644 --- a/src/SharpEmu.Libs/Np/NpTrophy2Exports.cs +++ b/src/SharpEmu.Libs/Np/NpTrophy2Exports.cs @@ -80,6 +80,25 @@ public static class NpTrophy2Exports LibraryName = "libSceNpTrophy2")] public static int NpTrophy2ShowTrophyList(CpuContext ctx) => ReturnOk(ctx); + /// + /// Gen5 ABI: context, handle, trophy id, then SceNpTrophy2Details and + /// SceNpTrophy2Data output pointers. + /// + /// + /// Reports "no such trophy" rather than succeeding. Succeeding would require + /// filling both output structures, and their exact layouts are not confirmed + /// here — a title that trusted zeroed details would read an empty name and a + /// grade of zero as real data. NOT_FOUND is a documented outcome that callers + /// must already handle, so it degrades along a path the game tests. + /// + [SysAbiExport( + Nid = "EwNylPdWUTM", + ExportName = "sceNpTrophy2GetTrophyInfo", + Target = Generation.Gen5, + LibraryName = "libSceNpTrophy2")] + public static int NpTrophy2GetTrophyInfo(CpuContext ctx) => + SetReturn(ctx, OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND); + private static int WriteIdAndReturn(CpuContext ctx, ulong outAddress, ref int nextId) { if (outAddress == 0)