fix(agc): implement sceAgcDcbSetUcRegisterDirect (#558)

Emit the 3-dword SET_UCONFIG_REG packet from the packed {offset,value}
in RSI. Unresolved calls left GPU config registers unset during
RenderThread/Main bring-up.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
MarcelMediaDev
2026-07-23 10:32:04 +01:00
committed by GitHub
parent d991e32b15
commit 8e5a0bfb19
+47
View File
@@ -1431,6 +1431,26 @@ public static partial class AgcExports
public static int DcbSetUcRegistersIndirect(CpuContext ctx) =>
DcbSetRegistersIndirect(ctx, RUcRegsIndirect, "uc");
[SysAbiExport(
Nid = "w4-d0n60hdo",
ExportName = "sceAgcDcbSetUcRegisterDirect",
Target = Generation.Gen5,
LibraryName = "libSceAgc")]
public static int DcbSetUcRegisterDirect(CpuContext ctx) =>
DcbSetRegisterDirect(ctx, ItSetUconfigReg, "uc");
[SysAbiExport(
Nid = "aP1Ki9G3++4",
ExportName = "sceAgcDcbSetUcRegisterDirectGetSize",
Target = Generation.Gen5,
LibraryName = "libSceAgc")]
public static int DcbSetUcRegisterDirectGetSize(CpuContext ctx)
{
// SET_UCONFIG_REG header + offset + value.
ctx[CpuRegister.Rax] = 3u * sizeof(uint);
return (int)ctx[CpuRegister.Rax];
}
[SysAbiExport(
Nid = "GIIW2J37e70",
ExportName = "sceAgcDcbSetIndexSize",
@@ -10814,6 +10834,33 @@ public static partial class AgcExports
return ReturnPointer(ctx, commandAddress);
}
private static int DcbSetRegisterDirect(CpuContext ctx, uint op, string registerSpace)
{
var commandBufferAddress = ctx[CpuRegister.Rdi];
// Uc/Cx/Sh register is passed by value as {u32 offset, u32 value} in RSI.
var packedRegister = ctx[CpuRegister.Rsi];
var registerOffset = (uint)(packedRegister & 0xFFFF_FFFFUL);
var registerValue = (uint)(packedRegister >> 32);
if (commandBufferAddress == 0)
{
return ReturnPointer(ctx, 0);
}
const uint packetDwords = 3;
if (!TryAllocateCommandDwords(ctx, commandBufferAddress, packetDwords, out var commandAddress) ||
!TryWriteUInt32(ctx, commandAddress, Pm4(packetDwords, op, 0)) ||
!TryWriteUInt32(ctx, commandAddress + 4, registerOffset & 0xFFFFu) ||
!TryWriteUInt32(ctx, commandAddress + 8, registerValue))
{
return ReturnPointer(ctx, 0);
}
TraceAgc(
$"agc.dcb_set_{registerSpace}_direct buf=0x{commandBufferAddress:X16} " +
$"cmd=0x{commandAddress:X16} offset=0x{registerOffset:X4} value=0x{registerValue:X8}");
return ReturnPointer(ctx, commandAddress);
}
private static bool TryAllocateCommandDwords(CpuContext ctx, ulong commandBufferAddress, uint sizeDwords, out ulong commandAddress)
{
commandAddress = 0;