Files
AnyPS5/docs/dev/debt/libSceAgc.md
T
Dean c3f49ea299 Merge pull request #10654 from akkadbakkad89/feat/agc-acb-workload
feat(libSceAgc): emit ACB workload packets for complete, active and stream-inactive
2026-10-28 13:49:41 +13:00

55 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# libSceAgc technical debt
### Unknown function info
- [sceAgcDcbSetCfRegisterDirect, sceAgcDcbSetCfRegisterRangeDirect](../../../core/libs/prx/libSceAgc/DcbState/src/Registers.cpp) (libSceAgc) - signatures follow [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/main/src/game_compat.c) and [SharpProspero](https://github.com/SvenGDK/SharpProspero/blob/main/src/SharpProspero/Interop/Agc/SceAgc.cs), which agree; the SET_CONFIG_REG (0x68) packet is OpenAGC's. The driver does not execute SET_CONFIG_REG, so a submitted packet throws
- [Command buffer cursors](../../../core/libs/prx/libSceAgc/Command/src/Packet.cpp) (libSceAgc) - a null `cursor_down` is taken as a buffer without downward allocations, whose limit is `top`. PPSA16064 builds one-packet buffers of 8 dwords that way; the console's handling is unconfirmed
- [sceAgcGetRegisterDefaultsInternal](../../../core/libs/prx/libSceAgc/Misc/src/RegisterDefaults.cpp) (libSceAgc) - returns the version 0 internal table while `sceAgcGetRegisterDefaults` now returns the version 13 public one; which internal table a console returns is not known. [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/main/src/game_compat.c) returns the table of the version passed to `sceAgcInit` instead, and null before it
- [sceAgcGetRegisterDefaults](../../../core/libs/prx/libSceAgc/Misc/src/RegisterDefaults.cpp) (libSceAgc) - returns the version 13 public table (137 keyed entries over 84 context blocks) because the console returns the running system software's table: [ps5-vulkan](https://github.com/mpereiraesaa/ps5-vulkan/blob/4bb0c8b1423698a7369efc22b829bf16a99e7128/src/color_runtime_defaults.h) measured 128 entries over 79 blocks on 10.x and 137 over 84 on 12.02 and 13.x, the shapes of the version 10 and version 11/13 tables here, and PPSA99011 refuses the version 0 table. The [type table](../../../core/libs/prx/libSceAgc/Command/src/RegisterDefaults.cpp) is handed out as 8-byte `{key, index << 2 | bank}` pairs, the layout ps5-vulkan and the homebrew sharing its `ps5_agc_registers.h` read; the compact 12-byte entries also pack the block's register count and stride above bit 10, and those bits are dropped. `sceAgcGetRegisterDefaults2`, `sceAgcGetRegisterDefaults2Internal`, `sceAgcGetRegisterDefaultsInternal` and `sceAgcInit` hand out the compact 12-byte entries (`RegisterDefaultsTypeLayout::Compact`): SDK-built code walks the tables of the first two with a 12-byte stride, reads the key at +0 and the bank and index from the low 10 bits of the word at +4, and keeps an all-ones sentinel for a key it does not find. Which layout the legacy internal call returns on a console is not known. No console dump of the runtime type table was compared, and AnyPS5 does not choose 10.x or 12.02 by the system software a title targets
- [sceAgcInit](../../../core/libs/prx/libSceAgc/DcbState/src/Init.cpp) (libSceAgc) - versions 0–13 select their register-default tables and return 0; pointer-shaped or otherwise out-of-range values (>=14) return 0 without a register-default lookup. Console probe on firmware 13.60 ([#4808](https://github.com/boykopovar/AnyPS5/issues/4808#issuecomment-6149448503)): `sceAgcInit(&buf, 8)` (NID `kW3GLb7QfPg`) returns 0 and writes nothing; scalar versions 2–13 return `0x8A6C0004` there, while AnyPS5 still returns 0 for those scalars. The probe does not show that table 13 is selected for pointer-shaped calls. [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/main/src/game_compat.c) returns `0x80890001` above 12 for `sceAgcInit`, and falls back to version 11 in `sceAgcGetRegisterDefaults2`. PPSA99011, PPSA99995, [ps5-vulkan](https://github.com/mpereiraesaa/ps5-vulkan) and [prospero-win](https://github.com/mpereiraesaa/prospero-win) call that NID with a pointer-shaped first argument. `sceAgcInit_0090` (NID `23LRUSvYu1M`) checks the state pointer and then calls `sceAgcInit`, as OpenAGC does
- [sceAgcSetSubmitMode](../../../core/libs/prx/libSceAgc/Misc/src/Suspend.cpp) (libSceAgc) - mode values unknown; only 0 is accepted
- [sceAgcGetGsOversubscription](../../../core/libs/prx/libSceAgc/Shader/src/GsOversubscription.cpp) (libSceAgc) - signature and occupancy formula (base and expanded vertex/export capacities, budget shift, `GE_PC_ALLOC` / `SPI_SHADER_PGM_RSRC4_GS` encoding) follow KytyPS5 only, not confirmed on hardware or a title; a negative or NaN factor that gives a negative target, a missing GS context register or a zero `GE_MAX_OUTPUT_PER_SUBGROUP` throws
- [sceAgcGetGsPrimPayload](../../../core/libs/prx/libSceAgc/Shader/src/GsPrimPayload.cpp) (libSceAgc) - the search does not stop at an `SPI_SHADER_IDX_FORMAT` (0x1C2) entry whose format is not `SPI_SHADER_2COMP`, as the analysis of the library declared in the pull request describes (its origin and firmware version are not identified), while [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c#L1285-L1310) stops there; not verified on PS5 hardware. A null payload, a null shader or a register count with a null register array throws instead of faulting on the memory access
- [sceAgcCbCondWrite](../../../core/libs/prx/libSceAgc/Cb/src/Branch.cpp) (libSceAgc) - argument order and the 9-dword COND_WRITE layout follow the clean-room [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/main/src/game_compat.c) and [sharpemu](https://github.com/sharpemu/sharpemu/blob/main/src/SharpEmu.Libs/Agc/AgcExports.CommandPackets.cs), which agree on them; SharpProspero lists another order. The write space is accepted only as 1 (memory), the one value both encode the same way, and other values throw.
- [sceAgcAcbAtomicGds_0900](../../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - signature, control/mode bit mapping and the 11-dword ATOMIC_GDS (0x1d) layout follow the clean-room [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c) only, which derives them from the library's disassembly; KytyPS5 and shadPS4 have no body for it. Not confirmed on hardware or a title (PPSA07286 imports it, nothing was run), and the driver has no ATOMIC_GDS handler (opcode 0x1d is not executed as an atomic GDS operation)
- [sceAgcGetIsTrinityMode](../../../core/libs/prx/libSceAgc/Misc/src/Platform.cpp) (libSceAgc) - signature from the only PPSA26344 call (a pointer to a one-byte flag, result ignored); a null pointer throws because its error code is unknown
- [sceAgcDcbAtomicGds_0900](../../../core/libs/prx/libSceAgc/DcbFlow/src/Control.cpp) (libSceAgc) - and `sceAgcDcbAtomicGds` (forwards to it) - signature, control/mode bit mapping and the 11-dword ATOMIC_GDS (0x1d) layout are those of `sceAgcAcbAtomicGds_0900`, which follow the clean-room [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c) only; KytyPS5 and shadPS4 have no body for it. Not confirmed on hardware or a title, and the driver has no ATOMIC_GDS handler
- [sceAgcDcbContextStateOp](../../../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - delegates to `sceAgcDcbContextStateOp_0100` (same packets as KytyPS5's `AgcDcbContextStateOp`); KytyPS5 returns nullptr for an operation above 3, here it throws; the packet words were not compared with a real console
- [sceAgcBranchPatchSetThenTarget_0300, sceAgcBranchPatchSetElseTarget_0300](../../../core/libs/prx/libSceAgc/Patch/src/Branch.cpp) (libSceAgc) - names from their NIDs (`7Wa3aeJgeVU`, `rP5xLdOf26k`); the `(packet, cachePolicy, target, sizeInDwords)` signature is inferred from PPSA28416's calls (a branch packet, 0, an aligned target, 4), with the policy stored where `sceAgcCbBranch` puts it
- [sceAgcDcbSet{Cx,Sh,Uc}RegistersIndirectGetSize](../../../core/libs/prx/libSceAgc/DcbState/src/Registers.cpp) (libSceAgc) - the count argument is ignored: PPSA28416 calls them with leftover register contents (0xf5f5039c), so the real functions likely take none; the size is 20 bytes either way
- [sceAgcCbSetShRegistersDirect, sceAgcCbSetUcRegistersDirect](../../../core/libs/prx/libSceAgc/Cb/src/Registers.cpp) (libSceAgc) - a register list may start at any byte address, and its 8-byte `{offset, value}` entries are copied byte for byte. PPSA26344 (02.002.000) passes the `sh_registers` lists of compute shader headers that sit 1 byte past an 8-byte boundary in `core_common_subcore.core_b1_fx.sprig.xpps` ([#902](https://github.com/boykopovar/AnyPS5/pull/902)), so those lists start at 1 mod 4 (0x8021363131 in an open-world run). The title runs on the console with these lists, but how the console reads an unaligned list (at the given address, or at a rounded-down one) is not measured
- [sceAgcUpdateInterpolantMapping_0100](../../../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - name from its NID (`k0E7vkgqAuE`); the `(regs, vs, ps)` arguments are the declared ones, behaviour unknown
- [sceAgcWriteDataPatchSetDst, sceAgcWriteDataPatchSetCachePolicy and their Async forms](../../../core/libs/prx/libSceAgc/Patch/src/WaitRegMem.cpp) (libSceAgc) - the signatures `(packet, uint8 value)` are inferred from the other patch functions, as no public declaration was found; the value is taken in the encoding of the `dst` and `cachePolicy` arguments of `sceAgcDcbWriteData` (graphics) and `sceAgcAcbWriteData` (Async, compute), and the patched packet is the one those calls would write. `sceAgcAsyncWriteDataPatchSetAddressOrOffset` is assumed to patch the address like `sceAgcWriteDataPatchSetAddressOrOffset`, as the compute WRITE_DATA packet keeps it in the same dwords
- [sceAgcCreateInterpolantMapping_10000](../../../core/libs/prx/libSceAgc/Shader/src/InterpolantMapping.cpp) (libSceAgc) - name from its NID (`dbOlWdppb4o`); same arguments as `sceAgcCreateInterpolantMapping_0100`; PPSA26344 passes three pointers at each of nine observed call sites (`0x9F914E`, `0x9F91E2`, `0x9F9216`, `0x1604BBD`, `0x16122D7`, `0x1618285`, `0x161838C`, `0x16184EE`, `0x1618607`), consistent with that argument assumption, but does not read the return value there, so its return type is not established.
- [sceAgcGetDataPacketPayloadRange](../../../core/libs/prx/libSceAgc/Misc/src/PacketInfo.cpp) (libSceAgc) - signature, the `{base, size in bytes}` output and the type 0 range (header + 1, one dword longer than the type 1 payload) from KytyPS5 only, matching `sceAgcGetDataPacketPayloadAddress_0090`; prosper returns header + 2 for both types from that address function
- [sceAgcGetDataPacketPayloadAddress](../../../core/libs/prx/libSceAgc/Misc/src/PacketInfo.cpp) (libSceAgc) - forward to `sceAgcGetDataPacketPayloadAddress_0090` and the inferred (addr, cmd, type) parameters follow SharpProspero and decrypted firmware 3.20 NID mapping; not verified on console hardware
- [sceAgcAcbMemSemaphore, sceAgcDcbMemSemaphore](../../../core/libs/prx/libSceAgc/Acb/src/Sync.cpp) (libSceAgc) - signature (cb, semaphoreAddr, waitForMailbox, signalType, operation) inferred from PPSA03396, whose wrapper passes the address second and operation 6 (signal) or 7 (wait) last; the three trailing arguments go to the packet as-is
- [sceAgcCbMemSemaphore](../../../core/libs/prx/libSceAgc/Cb/src/Sync.cpp) (libSceAgc) - signature (cb, semaphoreAddr, operation, modifier, value) follows SharpProspero; writes 4-dword PM4 0x39 packet with control word 0x80100000 following console oracle measurements in prosper (cases agcbuild_CbMemSemaphore_a/b/c); operation, modifier and value are unused
- [sceAgcAsyncCondExecPatchSetCommandAddress, sceAgcAsyncCondExecPatchSetEnd](../../../core/libs/prx/libSceAgc/Patch/src/CondExec.cpp) (libSceAgc) - no reference has a body for them; they are assumed to patch the COND_EXEC packet like `sceAgcCondExecPatchSetCommandAddress` and `sceAgcCondExecPatchSetEnd`, since `sceAgcAcbCondExec` writes the same packet as `sceAgcDcbCondExec`, as `sceAgcAsyncRewindPatchSetRewindState` does for REWIND
- [sceAgcAcbAtomicGds_0900](../../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - name from its NID (`gQkqkLttcpw`)
- [sceAgcCbMemsetExclusive](../../../core/libs/prx/libSceAgc/Unimplemented.cpp) (libSceAgc) - absent from the 4.03 `libSceAgc.sprx` export table together with the rest of the memset family (`sceAgcCbMemset`, `sceAgcDcbMemset`, `sceAgcDcbMemsetExclusive`, `sceAgcCbFill`, `sceAgcDcbFill`), so no body was read and the signature is unknown. It is a real export of newer firmware or SDK: PPSA20397 imports it through its `libSceJobManager.prx` and its generated fakelib lists it, but the only code path reaching it there is an import thunk no call site invokes, so no caller arguments were observed and the title runs without it. The name suggests a compute command buffer fill packet like the `sceAgcCb*` emitters write. A firmware 13.42 `libSceAgc.sprx` report (unverified here) has it as a 1121-byte body calling `sceAgcCbSetShRegistersDirect`, `memcpy` and six indirect calls through the command buffer's +0x20 function pointer.
- [sceAgcDcbPrimeUtcl2](../../../core/libs/prx/libSceAgc/DcbState/src/Display.cpp) (libSceAgc) - assumed to write the packet `sceAgcAcbPrimeUtcl2` writes: PRIME_UTCL2 has the same 5 dwords on the graphics and compute rings. Not confirmed on a title. Both write a NOP of that size, as there is no TLB to prime
- [sceAgcDcbQueueEndOfShaderActionGetSize](../../../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - the builder is inline in the SDK and not exported; the size is assumed to be that of the RELEASE_MEM packet `sceAgcCbReleaseMem` writes (32 bytes), the same as `sceAgcAcbQueueEndOfShaderActionGetSize`, as in [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/main/src/game_compat.c) and [REmu](https://github.com/xnetcat/REmu/blob/main/crates/remu-runtime/src/agc_dcb.rs)
- [sceAgcDcbSetZPassPredicationEnableGetSize, sceAgcDcbSetPredicationDisableGetSize, sceAgcDcbSetBoolPredicationEnableGetSize](../../../core/libs/prx/libSceAgc/DcbState/src/Predication.cpp) (libSceAgc) - the builders are inline in the SDK and not exported; the size is assumed to be that of the SET_PREDICATION packet `sceAgcDcbSetPredication` writes (16 bytes)
- [sceAgcAcbWaitUntilSafeForRendering](../../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - `(buffer, videoOutHandle, displayBufferIndex)`, the declared arguments, which PPSA12544 (01.000.010) passes inside `waitUntilSafeForRendering` and `waitUntilSafeForRendering VR` markers on an asynchronous compute command buffer, ignoring the result. It writes the same rendering-wait packet as `sceAgcDcbWaitUntilSafeForRendering`, which the driver now accepts on compute queues too; the wait blocks only that queue's worker. Whether the console encodes the compute variant differently is not known. In PPSA12544 the Acb function is called from 2 sites (0x11d9538, 0x11d95a4) and the Dcb function from 4 (0x11d76d4, 0x11d7740, 0x16e5eac, 0x16f32a6), each with three arguments and no read of the result; which of the last two arguments is the handle and which the index is not shown.
- [sceAgcGetDefaultCxStateFlat](../../../core/libs/prx/libSceAgc/Misc/src/RegisterDefaults.cpp) (libSceAgc) - copies up to `size` bytes (clamped to 2048 bytes, the 512-dword `AgcContextState`) from the default context state initialized from the version 8 public register default groups (CX, SH, UC), indexed by register offset, following OpenAGC `src/context_state.c`; returns `0x80890001` on null destination; version selection without `sceAgcInit` is unverified
- [sceAgcDcbSetIndexIndirectArgs, sceAgcDcbSetIndexIndirectArgsGetSize](../../../core/libs/prx/libSceAgc/DcbDraw/src/IndexBuffer.cpp) (libSceAgc) - the `(buffer, attributeAddress, attributeIndex)` signature, a 64-bit address and a 32-bit index, is [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c#L1742-L1757)'s. The console oracle in prosper measured the packet, an INDEX_ATTRIBUTES_INDIRECT (opcode 0x91) holding the low address dword, the high address dword and the index ([measured](https://github.com/mattias800/prosper/blob/3ea5cb9a846b6dcd00f5073360462bbda4f72288/prosper/tests/data/console_oracle/agcbuild.golden.tsv#L172-L174)), and a size of 16 bytes ([measured](https://github.com/mattias800/prosper/blob/3ea5cb9a846b6dcd00f5073360462bbda4f72288/prosper/tests/data/console_oracle/agc.golden.tsv#L67)). The console clears the low four address bits and keeps the low 16 bits of the index; here a nonzero address that is not 16-byte aligned, or an index above 0xffff, throws, as `sceAgcDcbSetIndexBuffer` throws for a misaligned address. A null address is written as 0, as the console writes it. No title is known to call them.
- [sceAgcSuspendPointAndCheckStatus](../../../core/libs/prx/libSceAgc/Export.cpp) - this named callable export is listed in the [PS5 3.20 export table](https://github.com/DNNDHH/PS5-3.20_Libs/blob/b2a77c09cd71c01f34c790cfbe98c751a13262ad/libSceAgc.c) and was cross-checked against the same module in PS5 firmware 13.60. Its signature and behaviour are unverified; the declaration uses the no-parameter unknown-signature convention and throws through `NotImplemented_nid_no_patch`.
- [sceAgcDcbDrawIndexMultiInstanced](../../../core/libs/prx/libSceAgc/DcbDraw/src/DrawIndexed.cpp) (libSceAgc) - what the arguments mean is not known. The function writes the console's 15 dwords (firmware 13.40, measured in a retail title): tag 0xc6000006, `DRAW_INDEX_MULTI_INST` (0x3a) with the first three arguments in order and the fourth twice (the first copy at least 1), initiator 0x80 whatever the modifier, then tag 0xc6000000; it checks no argument. The parameter names (index count, index address, object IDs, instance count) are unverified: AMD's PFP layout of the packet (instance count, object ID address, max size, index base, index count, initiator) would make them instance count, object ID address, index address and index count. The driver refuses the packet.
### Functional
- [sceAgcDebugRaiseException](../../../core/libs/prx/libSceAgc/Misc/src/Debug.cpp) (libSceAgc) - logs the exception id and returns 0, as retail hardware does nothing per [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c); the trap (`ud2`) OpenAGC describes for development hardware is not reproduced. Neither is verified on a console. The `uint32` exception id is [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/6f0cddd4404ec5203e71fea77e75fc373299ba3f/src/libs/agc.cpp)'s claim, and a second argument is not declared: OpenAGC declares no arguments, but PPSA21564 01.007.000 passes two, 1 in `edi` and 0 in `esi`, from the callback its command buffers get when none is given (0x6f3b6a0), and ignores the result. The second argument's type and meaning are not identified. PPSA01494, PPSA03984, PPSA18194, PPSA30839, PPSA31162 and PPSA34502 call it the same way, once each, with 1 and 0 and the result ignored.
- [sceAgcSetAmmSemaphoreMemory, sceAgcSetSemaphoreMemory, sceAgcGetSemaphoreLabel](../../../core/libs/prx/libSceAgc/Misc/src/Semaphore.cpp) (libSceAgc) - the checks, error codes and clearing are the firmware's, but two firmware steps are not reproduced. After its checks, the firmware validates the memory with libkernel `qSleeVC6lwI`: an ioctl `0xc018ac15` taking `{memory, size, 1}`. The AMM call always does this; the non-AMM call only for memory from 8 TiB up that ends below 15 TiB. The firmware then sends `{7: memory, 8: size, 0xb: 0 for AMM, 1 otherwise}` through sceAgcDriverPassInfoDownward. Neither step happens here, so a registration that the kernel or driver would refuse succeeds. A null memory with a non-zero size and a range that wraps the address space throw where the firmware would fault
- [sceAgcDcbSetWorkloadsActive and sceAgcDcbSetWorkloadComplete](../../../core/libs/prx/libSceAgc/DcbState/src/Workload.cpp) (libSceAgc) - the DCB calls write the packets [KytyPS5](https://github.com/KytyPS5/KytyPS5/blob/main/src/libs/agc.cpp) writes: an 18-dword (active) or 12-dword (complete) `IT_NOP` packet with the stream id, and for active the 64-bit mask of the workload ids, for complete the workload id and the 64-bit clear mask of that id. Both return null for a null command buffer, an unregistered or out-of-range stream, a workload id above 63, and for active a duplicate id or a count of 0 or above 63. The layouts and checks come from KytyPS5 alone; the console oracle in [prosper](https://github.com/mattias800/prosper/blob/main/prosper/tests/data/console_oracle/agcbuild.golden.tsv) measures the null return only for unregistered streams, not the packet contents of a registered one. PPSA29866 calls sceAgcDcbSetWorkloadsActive while building its command buffers (sceAgcDcbSetWorkloadComplete was not observed); nothing else was observed.
- [sceAgcAcbSetWorkloadsActive, sceAgcAcbSetWorkloadComplete, sceAgcAcbSetWorkloadStreamInactive](../../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - return null without writing to the buffer for a null command buffer or an unregistered stream; for a registered stream they write the same `IT_NOP` packets the DCB calls write: 18, 12 and 9 dwords carrying the stream id, the 64-bit active mask, the workload id plus its clear mask. The sizes match the firmware 4.03 `libSceAgcDriver.sprx` packet-size helpers, and the ACB emitter writes the identical packet with only the queue flag differing. The packets are inert here: `Pm4::Execute` returns on a NOP with operation 0 without reading the payload, so no workload state is tracked; the console's SET_UCONFIG_REG/WRITE_DATA/ATOMIC_MEM sequence below is not written. prosper's oracle measured only the null return for unregistered streams. No ACB declaration was found; OpenAGC says the ACB calls share the DCB driver builders
- [sceAgcDcbSetWorkloadStreamInactive](../../../core/libs/prx/libSceAgc/DcbState/src/Workload.cpp) (libSceAgc) - returns null without writing to the buffer for a null command buffer or an unregistered stream, and throws for a registered stream. prosper's oracle measured only that null return, with no stream registered; the packet a registered stream gets is not measured. KytyPS5 has no body for it; its `IT_NOP` layout for the DCB active and complete calls differs from the SET_UCONFIG_REG, WRITE_DATA and SET_WORKLOAD sequence OpenAGC derives from the driver, so neither is taken. The `(buf, streamId)` signature is that of the DCB call in OpenAGC, which says the ACB calls use the same driver builders. `sceAgcDcbSetWorkloadsActive` checks the stream before reading the workload ids, as OpenAGC does: the console returned null for stream 1 with the ids at address 2 without faulting
- [sceAgcDcbSetWorkload*](../../../core/libs/prx/libSceAgc/DcbState/src/Workload.cpp) and [sceAgcAcbSetWorkload*](../../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - the console's packets are not written: the executor has no ATOMIC_MEM or mask table. In `libSceAgc.sprx` (firmware 13.60, read from disassembly) all six write a SET_UCONFIG_REG to 0x342 (tag `0xCC000000 | stream`, or `0xCD000000 + workload * 32 + stream` for complete) and a WRITE_DATA to 0xC343, and active and complete add an ATOMIC_MEM (header `0xC0071E00`) on the stream's 64-bit mask. [Measured on a PS5](https://gist.github.com/orezraey/befe7632b827421988b47a6c04e89e1d) (firmware 13.60): WRITE_DATA dwords 5 to 8 are `0x06010000`, `0xC343`, 0 and the mask's high half (0 for inactive); the header low byte is 0x04 on the DCB SET_UCONFIG_REG and WRITE_DATA and 0x00 on the ACB ones; the table was at `0xFE003A000 + 8 * stream`; the pointer passed to `sceAgcDriverRegisterWorkloadStream` is never written
- [sceAgcCreatePrimState](../../../core/libs/prx/libSceAgc/Shader/src/PrimState.cpp) (libSceAgc) - the `ge_user_vgpr_en` special is passed to the user configuration registers at whatever offset the shader header stores, as the SPRX does according to [OpenAGC](https://github.com/OpenAGC/OpenAGC/blob/3c7e8072f0d7684e930454794fd5c02056946d73/src/game_compat.c#L1181-L1252), which copies all four specials verbatim (KytyPS5 stops on any other offset). PPSA99039, PPSA99505, PPSA99515 and PPSA99997 build their headers by hand with it at 0x25c (`GE_USER_VGPR1`) instead of 0x262 (`GE_USER_VGPR_EN`), value 0, and run on the console; it is not moved to 0x262, and the driver reads neither register. `ge_cntl`, `vgt_shader_stages_en` and a used `vgt_gs_out_prim_type` must still be at their own offsets, since the driver reads those registers there, so a header that stores one elsewhere throws naming the offset, although by OpenAGC the SPRX would copy it as well
- [sceAgcDcbEventWrite](../../../core/libs/prx/libSceAgc/DcbFlow/src/Sync.cpp) (libSceAgc) - non-sample-dump event types (any event other than 0x38 and 0x39) emit a 2-dword PM4 packet 0x46 without address dwords; the address argument is ignored for these events. Void Terrarium (PPSA03061, #5055) passes a non-null address buffer (0x00000002d2a10000) with event type 0x16 (cache flush).
- This pending declaration has an unverified signature and behavior; it is a parameterless import-resolution declaration that throws through `NotImplemented_nid_no_patch`: [`sceAgcAcbInitializeDefaultHardwareState`](../../../core/libs/prx/libSceAgc/Unimplemented.cpp).
- [sceAgcAcquireMemSetEngine, sceAgcCbMemsetExclusive](../../../core/libs/prx/libSceAgc/Unimplemented.cpp) (libSceAgc) - declared with canonical signatures from decrypted headers; behavior on retail consoles remains unmeasured. Both throw through `NotImplemented_nid_no_patch`. Six title binaries import `sceAgcCbMemsetExclusive` through a jump stub and call that stub at 12 sites (PPSA15246 0x6dcaf8, 0x6dd029; PPSA21480 0xc9e51, 0xca369; PPSA23827 0x54e5f0, 0x54eb51; PPSA24423 0x41768, 0x41c89; PPSA24779 0xc23f78, 0xc24499; PPSA35169 0x6eef90, 0x6ef4f1). At four sites read in the listing (PPSA21480 0xc9e51 and 0xca369, PPSA24423 0x41768, PPSA35169 0x6eef90) when the call returns 0, the calling function returns 0x8a6c002b instead of aborting, and at 0x41768 the call is made only for a flag byte of 1 and a size of at least 0x40000. Whether a title reaches these calls was not measured.