mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
agc: implement sceAgcSetNop (#1343)
* agc: implement sceAgcSetNop Star Wars Outlaws calls sceAgcSetNop (K2mciNVxUCE) and crashes right after the unresolved stub returns, without the packet being disabled. The call turns a packet into a NOP of the same length. Clear the emulator's custom NOP code as well, so packets that the HLE encodes as NOPs, such as end-of-pipe actions, stop executing too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * agc: keep packets disabled by sceAgcSetNop from reading as markers A disabled packet whose first payload word carries the 0x6875 marker signature still reached the marker handler, which can flip or stop on an unknown marker ID. Clear the signature so the packet is skipped like any other NOP. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * agc: tidy SetNop logging and comments --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: nmzik <Nmzik@mail.ru>
This commit is contained in:
@@ -42630,6 +42630,43 @@ void CheckPm4IndirectControlFlow(RenderContext &renderer) {
|
||||
Gen5::AgcCbNop(reinterpret_cast<Gen5::CommandBuffer*>(&payload_dcb), 3) == payload.data() &&
|
||||
payload == std::array<uint32_t, 3>{0xc0011000u, 0x12345678u, 0x9abcdef0u},
|
||||
"NOP emitter overwrote the caller's reserved payload");
|
||||
alignas(8) uint64_t released = 0;
|
||||
std::array<uint32_t, 20> disabled_commands{};
|
||||
const auto disabled_write = write(&returned, 99);
|
||||
std::copy(disabled_write.begin(), disabled_write.end(), disabled_commands.begin());
|
||||
disabled_commands[5] = KYTY_PM4(2, Pm4::IT_NUM_INSTANCES, 0);
|
||||
disabled_commands[6] = 0x68750123u;
|
||||
CommandBufferLayout release_dcb{disabled_commands.data() + 7, disabled_commands.data() + 15,
|
||||
disabled_commands.data() + 7, disabled_commands.data() + 15, nullptr, nullptr, 0};
|
||||
auto* release = Gen5::AgcCbReleaseMem(
|
||||
reinterpret_cast<Gen5::CommandBuffer*>(&release_dcb), 0x28, 0, 0, 0,
|
||||
reinterpret_cast<const volatile Gen5::Label*>(&released), 2, 77, 0, 0, 0, 0);
|
||||
const auto enabled_write = write(&selected, 88);
|
||||
std::copy(enabled_write.begin(), enabled_write.end(), disabled_commands.begin() + 15);
|
||||
const auto unpatched_commands = disabled_commands;
|
||||
Require(name, "SetNop packets",
|
||||
release == disabled_commands.data() + 7 &&
|
||||
Gen5::AgcSetNop(disabled_commands.data()) == 0 &&
|
||||
Gen5::AgcSetNop(disabled_commands.data() + 5) == 0 && Gen5::AgcSetNop(release) == 0 &&
|
||||
disabled_commands[0] == ((disabled_write[0] & 0xffff00ffu) | (Pm4::IT_NOP << 8u)) &&
|
||||
disabled_commands[5] == KYTY_PM4(2, Pm4::IT_NOP, Pm4::R_ZERO) &&
|
||||
disabled_commands[6] == 0x123u &&
|
||||
release[0] == KYTY_PM4(8, Pm4::IT_NOP, Pm4::R_ZERO) &&
|
||||
unpatched_commands[7] == KYTY_PM4(8, Pm4::IT_NOP, Pm4::R_RELEASE_MEM) &&
|
||||
Gen5::AgcGetPacketSize(disabled_commands.data()) == disabled_write.size() &&
|
||||
Gen5::AgcGetPacketSize(disabled_commands.data() + 5) == 2 &&
|
||||
Gen5::AgcGetPacketSize(release) == 8 &&
|
||||
std::equal(disabled_commands.begin() + 1, disabled_commands.begin() + 5,
|
||||
unpatched_commands.begin() + 1) &&
|
||||
std::equal(disabled_commands.begin() + 8, disabled_commands.end(),
|
||||
unpatched_commands.begin() + 8),
|
||||
"SetNop changed a packet length, kept its operation or marker, or touched its payload");
|
||||
selected = returned = 0;
|
||||
Pm4Execution disabled_execution;
|
||||
Require(name, "SetNop execution",
|
||||
processor.Process(disabled_execution, disabled_commands) == Pm4ProcessResult::Complete &&
|
||||
returned == 0 && released == 0 && selected == 88,
|
||||
"a disabled packet still executed or hid the packet after it");
|
||||
const auto then_commands = write(&selected, 11);
|
||||
const auto else_commands = write(&selected, 33);
|
||||
const auto branch_suffix = write(&selected, 44);
|
||||
|
||||
Reference in New Issue
Block a user