Merge pull request #1215 from polysius/fix/agc-versioned-nid-names
refactor(libSceAgc): name exports after the versioned SDK names their NIDs hash to
This commit is contained in:
commit
ac951f8d09
|
|
@ -12,8 +12,7 @@
|
|||
extern "C" {
|
||||
|
||||
// unknown signature
|
||||
APS5_EXPORT("gQkqkLttcpw", sceAgcAcb_gQkqkLttcpw);
|
||||
void* APS5_VABI sceAgcAcb_gQkqkLttcpw (void) {
|
||||
void* APS5_VABI sceAgcAcbAtomicGds_0900(void) {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ std::uint32_t APS5_VABI sceAgcDcbSetIndexSizeGetSize() {
|
|||
return 12;
|
||||
}
|
||||
|
||||
APS5_EXPORT("-KRzWekV120", sceAgcUnknown__MKRzWekV120);
|
||||
std::uint32_t* APS5_VABI sceAgcUnknown__MKRzWekV120(CommandBuffer* buf, std::uint8_t indexSize, std::uint8_t cachePolicy, std::uint8_t perInstanceObjectId) {
|
||||
std::uint32_t* APS5_VABI sceAgcDcbSetIndexSize_0600(CommandBuffer* buf, std::uint8_t indexSize, std::uint8_t cachePolicy, std::uint8_t perInstanceObjectId) {
|
||||
Agc::Command::CheckBits(perInstanceObjectId, 1, __func__);
|
||||
auto* packet = sceAgcDcbSetIndexSize(buf, indexSize, cachePolicy);
|
||||
packet[2] |= static_cast<std::uint32_t>(perInstanceObjectId) << 14u;
|
||||
|
|
|
|||
|
|
@ -26,8 +26,7 @@ uint64_t APS5_VABI sceAgcDcbContextStateOpGetSize(uint32_t operation) {
|
|||
return 27 * sizeof(std::uint32_t);
|
||||
}
|
||||
|
||||
APS5_EXPORT("qj7QZpgr9Uw", sceAgcDcbContextStateAnotherOp);
|
||||
uint32_t* APS5_VABI sceAgcDcbContextStateAnotherOp(CommandBuffer* buf, uint32_t operation) {
|
||||
uint32_t* APS5_VABI sceAgcDcbContextStateOp_0100(CommandBuffer* buf, uint32_t operation) {
|
||||
Agc::Command::Require(buf != nullptr, __func__, "null command buffer");
|
||||
Agc::Command::Require(operation <= 3, __func__, "invalid context state operation");
|
||||
const auto* function = __func__;
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@
|
|||
|
||||
extern "C" {
|
||||
|
||||
APS5_EXPORT("23LRUSvYu1M", sceAgcUnknownInitState);
|
||||
int APS5_VABI sceAgcUnknownInitState(std::uint32_t* state, std::uint32_t version) {
|
||||
int APS5_VABI sceAgcInit_0090(std::uint32_t* state, std::uint32_t version) {
|
||||
Agc::Command::CheckAddress(reinterpret_cast<std::uintptr_t>(state), alignof(std::uint32_t), __func__);
|
||||
Agc::Command::Require(version < 14, __func__, "unsupported AGC initialization version");
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ struct SizeAlign {
|
|||
std::size_t m_align;
|
||||
};
|
||||
|
||||
extern "C" int APS5_VABI sceAgcUnknownFuseShaderHalves(Shader* fused_result, const Shader* front, const Shader* back, void* scratch_mem);
|
||||
extern "C" int APS5_VABI sceAgcUnknownGetFusedShaderSize(SizeAlign* dst, const Shader* front, const Shader* back);
|
||||
extern "C" int APS5_VABI sceAgcFuseShaderHalves_0200(Shader* fused_result, const Shader* front, const Shader* back, void* scratch_mem);
|
||||
extern "C" int APS5_VABI sceAgcGetFusedShaderSize_0080(SizeAlign* dst, const Shader* front, const Shader* back);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ uint32_t APS5_VABI sceAgcGetPacketSize(uint32_t* packet) {
|
|||
return ((packet[0] >> 16u) & 0x3fffu) + 2u;
|
||||
}
|
||||
|
||||
APS5_EXPORT("V++UgBtQhn0", sceAgcGetDataPacketPayloadAddressUnk);
|
||||
int APS5_VABI sceAgcGetDataPacketPayloadAddressUnk(uint32_t** addr, uint32_t* cmd, int type) {
|
||||
int APS5_VABI sceAgcGetDataPacketPayloadAddress_0090(uint32_t** addr, uint32_t* cmd, int type) {
|
||||
Agc::Command::CheckAddress(reinterpret_cast<std::uintptr_t>(addr), alignof(uint32_t*), __func__);
|
||||
Agc::Command::CheckAddress(reinterpret_cast<std::uintptr_t>(cmd), alignof(uint32_t), __func__);
|
||||
if (type != 0) {
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ ShaderRegister& FindRegister(ShaderRegister* regs, std::uint32_t count, std::uin
|
|||
for (std::uint32_t i = 0; regs != nullptr && i < count; ++i) {
|
||||
if (regs[i].offset == offset && occurrence-- == 0) return regs[i];
|
||||
}
|
||||
throw std::runtime_error("sceAgcUnknownFuseShaderHalves: shader half lacks register " + std::to_string(offset));
|
||||
throw std::runtime_error("sceAgcFuseShaderHalves_0200: shader half lacks register " + std::to_string(offset));
|
||||
}
|
||||
|
||||
void MergeMax(ShaderRegister& dst, const ShaderRegister& src, std::uint32_t shift, std::uint32_t mask) {
|
||||
|
|
@ -188,11 +188,11 @@ void SetProgramAddress(std::vector<ShaderRegister>& regs, std::uint32_t loOffset
|
|||
regs[i + 1].value = (regs[i + 1].value & 0xFFFFFF00u) | static_cast<std::uint32_t>((address >> 40u) & 0xFFu);
|
||||
return;
|
||||
}
|
||||
throw std::runtime_error("sceAgcUnknownFuseShaderHalves: back half has no program address register pair");
|
||||
throw std::runtime_error("sceAgcFuseShaderHalves_0200: back half has no program address register pair");
|
||||
}
|
||||
|
||||
int FuseGeometryHalves(Shader* fused_result, const Shader* front, const Shader* back, void* scratch_mem) {
|
||||
constexpr auto fn = "sceAgcUnknownFuseShaderHalves";
|
||||
constexpr auto fn = "sceAgcFuseShaderHalves_0200";
|
||||
if (scratch_mem == nullptr) Fail(fn, "geometry halves need fused shader memory");
|
||||
auto layout = ComputeGeometryLayout(fn, front, back);
|
||||
const auto scratch = reinterpret_cast<std::uintptr_t>(scratch_mem);
|
||||
|
|
@ -252,8 +252,7 @@ int FuseGeometryHalves(Shader* fused_result, const Shader* front, const Shader*
|
|||
|
||||
extern "C" {
|
||||
|
||||
APS5_EXPORT("fd5Bp5tGTgo", sceAgcUnknownFuseShaderHalves);
|
||||
int APS5_VABI sceAgcUnknownFuseShaderHalves(Shader* fused_result, const Shader* front, const Shader* back, void* scratch_mem) {
|
||||
int APS5_VABI sceAgcFuseShaderHalves_0200(Shader* fused_result, const Shader* front, const Shader* back, void* scratch_mem) {
|
||||
if (fused_result == nullptr || front == nullptr || back == nullptr) APS5_INVALID_ARG_EX;
|
||||
if (!ValidHalves(front, back)) return GRAPHICS5_ERROR_INVALID_SHADER_HALVES;
|
||||
const bool isGs = GeometryHalves(front);
|
||||
|
|
@ -299,15 +298,14 @@ int APS5_VABI sceAgcUnknownFuseShaderHalves(Shader* fused_result, const Shader*
|
|||
}
|
||||
|
||||
int APS5_VABI sceAgcFuseShaderHalves_nid_postfix(Shader* fused_result, const Shader* front, const Shader* back, void* scratch_mem) {
|
||||
return sceAgcUnknownFuseShaderHalves(fused_result, front, back, scratch_mem);
|
||||
return sceAgcFuseShaderHalves_0200(fused_result, front, back, scratch_mem);
|
||||
}
|
||||
|
||||
APS5_EXPORT("dolOmWH+huQ", sceAgcUnknownGetFusedShaderSize);
|
||||
int APS5_VABI sceAgcUnknownGetFusedShaderSize(SizeAlign* dst, const Shader* front, const Shader* back) {
|
||||
int APS5_VABI sceAgcGetFusedShaderSize_0080(SizeAlign* dst, const Shader* front, const Shader* back) {
|
||||
if (dst == nullptr || front == nullptr || back == nullptr) APS5_INVALID_ARG_EX;
|
||||
if (!ValidHalves(front, back)) return GRAPHICS5_ERROR_INVALID_SHADER_HALVES;
|
||||
if (GeometryHalves(front)) {
|
||||
const auto layout = ComputeGeometryLayout("sceAgcUnknownGetFusedShaderSize", front, back);
|
||||
const auto layout = ComputeGeometryLayout("sceAgcGetFusedShaderSize_0080", front, back);
|
||||
dst->m_size = layout.totalBytes + FusedCodeAlignment - 1;
|
||||
dst->m_align = FusedCodeAlignmentLog2;
|
||||
return 0;
|
||||
|
|
@ -317,8 +315,7 @@ int APS5_VABI sceAgcUnknownGetFusedShaderSize(SizeAlign* dst, const Shader* fron
|
|||
return 0;
|
||||
}
|
||||
|
||||
APS5_EXPORT("k0E7vkgqAuE", sceAgcCreateInterpolantMappingVsPs);
|
||||
int APS5_VABI sceAgcCreateInterpolantMappingVsPs(ShaderRegister* regs, const Shader* vs, const Shader* ps) {
|
||||
int APS5_VABI sceAgcUpdateInterpolantMapping_0100(ShaderRegister* regs, const Shader* vs, const Shader* ps) {
|
||||
(void)regs;
|
||||
(void)vs;
|
||||
(void)ps;
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@ int APS5_VABI sceAgcJumpPatchSetTarget(uint32_t* cmd, const volatile uint32_t* t
|
|||
return 0;
|
||||
}
|
||||
|
||||
APS5_EXPORT("Ikfdt-rIqCE", sceAgcUnknown_Ikfdt_MrIqCE);
|
||||
int APS5_VABI sceAgcUnknown_Ikfdt_MrIqCE(uint32_t* cmd, uint64_t cache_policy, const volatile uint32_t* target, uint32_t size_in_dwords) {
|
||||
int APS5_VABI sceAgcJumpPatchSetTarget_0300(uint32_t* cmd, uint64_t cache_policy, const volatile uint32_t* target, uint32_t size_in_dwords) {
|
||||
Agc::Command::CheckBits(cache_policy, 3u, __func__);
|
||||
PatchJump(cmd, target, size_in_dwords, __func__);
|
||||
cmd[3] = (cmd[3] & ~(3u << 28u)) | (static_cast<std::uint32_t>(cache_policy) << 28u);
|
||||
|
|
|
|||
|
|
@ -80,8 +80,7 @@ int APS5_VABI sceAgcCbMemsetExclusive() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
APS5_EXPORT("7Wa3aeJgeVU", sceAgcUnknown_7Wa3aeJgeVU);
|
||||
int APS5_VABI sceAgcUnknown_7Wa3aeJgeVU() {
|
||||
int APS5_VABI sceAgcBranchPatchSetThenTarget_0300() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -101,8 +100,7 @@ int APS5_VABI sceAgcGetShaderInstrumentation() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
APS5_EXPORT("rP5xLdOf26k", sceAgcUnknown_rP5xLdOf26k);
|
||||
int APS5_VABI sceAgcUnknown_rP5xLdOf26k() {
|
||||
int APS5_VABI sceAgcBranchPatchSetElseTarget_0300() {
|
||||
NotImplemented_nid_no_patch(__func__);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,15 +18,15 @@ extern "C" int APS5_VABI sceAgcInit(std::uint32_t version);
|
|||
extern "C" void* APS5_VABI sceAgcGetRegisterDefaults();
|
||||
extern "C" void* APS5_VABI sceAgcGetRegisterDefaultsInternal();
|
||||
extern "C" void* APS5_VABI sceAgcGetRegisterDefaults2Internal(std::uint32_t version);
|
||||
extern "C" int APS5_VABI sceAgcUnknownInitState(std::uint32_t* state, std::uint32_t version);
|
||||
extern "C" int APS5_VABI sceAgcInit_0090(std::uint32_t* state, std::uint32_t version);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexAuto(CommandBuffer* buf, std::uint32_t indexCount, std::uint64_t modifier);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirect(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint64_t modifier);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbDrawIndexIndirectMulti(CommandBuffer* buf, std::uint32_t dataOffsetInBytes, std::uint32_t countIndirect, std::uint32_t maxCountOrCount, const volatile void* countAddress, std::uint32_t strideInBytes, std::uint64_t modifier);
|
||||
extern "C" int APS5_VABI sceAgcWaitRegMemPatchReference(std::uint32_t* cmd, std::uint64_t reference);
|
||||
extern "C" int APS5_VABI sceAgcWaitRegMemPatchMask(std::uint32_t* cmd, std::uint64_t mask);
|
||||
extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddressUnk(std::uint32_t** addr, std::uint32_t* cmd, int type);
|
||||
extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddress_0090(std::uint32_t** addr, std::uint32_t* cmd, int type);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcCbSetShRegisterRangeDirect(CommandBuffer* buf, std::uint32_t offset, const std::uint32_t* values, std::uint32_t numValues);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbContextStateAnotherOp(CommandBuffer* buf, std::uint32_t operation);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbContextStateOp_0100(CommandBuffer* buf, std::uint32_t operation);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbPushMarker(CommandBuffer* buf, const char* str, std::uint32_t color);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbPopMarker(CommandBuffer* buf);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbSetMarker(CommandBuffer* buf, const char* str, std::uint32_t color);
|
||||
|
|
@ -228,7 +228,7 @@ void testContextState() {
|
|||
source.buffer.reserved_dw = 2;
|
||||
source.buffer.callback = growContext;
|
||||
source.buffer.user_data = &growth;
|
||||
auto* first = sceAgcDcbContextStateAnotherOp(&source.buffer, operation);
|
||||
auto* first = sceAgcDcbContextStateOp_0100(&source.buffer, operation);
|
||||
check(first == (split == 0 ? growth.destination.words.data() : source.words.data()), "incorrect first context packet address");
|
||||
check(growth.calls == (requested == 0 ? 0u : 1u), "incorrect context callback count");
|
||||
auto* end = requested == 0 ? source.words.data() + totals[operation] : growth.destination.words.data() + totals[operation] - split;
|
||||
|
|
@ -249,24 +249,24 @@ void testContextState() {
|
|||
}
|
||||
}
|
||||
}
|
||||
expectFailure([] { sceAgcDcbContextStateAnotherOp(nullptr, 0); });
|
||||
expectFailure([] { sceAgcDcbContextStateOp_0100(nullptr, 0); });
|
||||
Storage invalid;
|
||||
expectFailure([&] { sceAgcDcbContextStateAnotherOp(&invalid.buffer, 4); });
|
||||
expectFailure([&] { sceAgcDcbContextStateOp_0100(&invalid.buffer, 4); });
|
||||
check(invalid.buffer.cursor_up == invalid.words.data(), "invalid context operation advanced cursor");
|
||||
invalid.buffer.cursor_up = invalid.words.data() + 1;
|
||||
invalid.buffer.cursor_down = invalid.words.data();
|
||||
expectFailure([&] { sceAgcDcbContextStateAnotherOp(&invalid.buffer, 0); });
|
||||
expectFailure([&] { sceAgcDcbContextStateOp_0100(&invalid.buffer, 0); });
|
||||
invalid.buffer.cursor_up = invalid.words.data();
|
||||
expectFailure([&] { sceAgcDcbContextStateAnotherOp(&invalid.buffer, 1); });
|
||||
expectFailure([&] { sceAgcDcbContextStateOp_0100(&invalid.buffer, 1); });
|
||||
ContextGrowth growth{{}, invalid.words.data(), 22};
|
||||
invalid.buffer.callback = growContext;
|
||||
invalid.buffer.user_data = &growth;
|
||||
growth.success = false;
|
||||
expectFailure([&] { sceAgcDcbContextStateAnotherOp(&invalid.buffer, 1); });
|
||||
expectFailure([&] { sceAgcDcbContextStateOp_0100(&invalid.buffer, 1); });
|
||||
growth.calls = 0;
|
||||
growth.success = true;
|
||||
growth.destination.buffer.cursor_down = growth.destination.words.data() + 21;
|
||||
expectFailure([&] { sceAgcDcbContextStateAnotherOp(&invalid.buffer, 1); });
|
||||
expectFailure([&] { sceAgcDcbContextStateOp_0100(&invalid.buffer, 1); });
|
||||
check(invalid.buffer.cursor_up == growth.destination.words.data(), "failed reservation advanced cursor");
|
||||
}
|
||||
|
||||
|
|
@ -328,19 +328,19 @@ void testPacketPayloadAddress() {
|
|||
Storage storage;
|
||||
auto* packet = sceAgcCbSetShRegisterRangeDirect(&storage.buffer, 0x8c, nullptr, 4);
|
||||
std::uint32_t* payload = nullptr;
|
||||
check(sceAgcGetDataPacketPayloadAddressUnk(&payload, packet, 1) == 0 && payload == packet + 2, "incorrect register packet payload address");
|
||||
check(sceAgcGetDataPacketPayloadAddress_0090(&payload, packet, 1) == 0 && payload == packet + 2, "incorrect register packet payload address");
|
||||
const std::array<std::uint32_t, 4> values{11, 22, 33, 44};
|
||||
std::copy(values.begin(), values.end(), payload);
|
||||
const std::array<std::uint32_t, 6> expected{0xc0047600u, 0x8c, 11, 22, 33, 44};
|
||||
check(std::equal(expected.begin(), expected.end(), packet), "payload write corrupted register packet");
|
||||
check(sceAgcGetDataPacketPayloadAddressUnk(&payload, packet, 0) == 0 && payload == packet + 1, "incorrect generic packet payload address");
|
||||
check(sceAgcGetDataPacketPayloadAddress_0090(&payload, packet, 0) == 0 && payload == packet + 1, "incorrect generic packet payload address");
|
||||
packet[0] = 0xffff1000u;
|
||||
check(sceAgcGetDataPacketPayloadAddressUnk(&payload, packet, 0) == 0 && payload == nullptr, "empty payload marker was not recognized");
|
||||
check(sceAgcGetDataPacketPayloadAddressUnk(&payload, packet, -1) == 0 && payload == packet + 2, "nonzero payload type did not skip two words");
|
||||
expectFailure([&] { sceAgcGetDataPacketPayloadAddressUnk(nullptr, packet, 1); });
|
||||
expectFailure([&] { sceAgcGetDataPacketPayloadAddressUnk(&payload, nullptr, 1); });
|
||||
check(sceAgcGetDataPacketPayloadAddress_0090(&payload, packet, 0) == 0 && payload == nullptr, "empty payload marker was not recognized");
|
||||
check(sceAgcGetDataPacketPayloadAddress_0090(&payload, packet, -1) == 0 && payload == packet + 2, "nonzero payload type did not skip two words");
|
||||
expectFailure([&] { sceAgcGetDataPacketPayloadAddress_0090(nullptr, packet, 1); });
|
||||
expectFailure([&] { sceAgcGetDataPacketPayloadAddress_0090(&payload, nullptr, 1); });
|
||||
auto* misaligned = reinterpret_cast<std::uint32_t*>(reinterpret_cast<unsigned char*>(packet) + 1);
|
||||
expectFailure([&] { sceAgcGetDataPacketPayloadAddressUnk(&payload, misaligned, 0); });
|
||||
expectFailure([&] { sceAgcGetDataPacketPayloadAddress_0090(&payload, misaligned, 0); });
|
||||
check(payload == packet + 2, "invalid packet changed output address");
|
||||
}
|
||||
|
||||
|
|
@ -373,10 +373,10 @@ void testMemory() {
|
|||
|
||||
void testDefaults() {
|
||||
std::uint32_t state = 0x12345678;
|
||||
check(sceAgcUnknownInitState(&state, 8) == 0 && state == 0x12345678, "AGC initialization failed or modified caller state");
|
||||
check(sceAgcUnknownInitState(&state, 13) == 0 && state == 0x12345678, "AGC version 13 initialization changed caller state");
|
||||
expectFailure([] { sceAgcUnknownInitState(nullptr, 8); });
|
||||
expectFailure([&] { sceAgcUnknownInitState(&state, 14); });
|
||||
check(sceAgcInit_0090(&state, 8) == 0 && state == 0x12345678, "AGC initialization failed or modified caller state");
|
||||
check(sceAgcInit_0090(&state, 13) == 0 && state == 0x12345678, "AGC version 13 initialization changed caller state");
|
||||
expectFailure([] { sceAgcInit_0090(nullptr, 8); });
|
||||
expectFailure([&] { sceAgcInit_0090(&state, 14); });
|
||||
check(sceAgcInit(8) == 0, "AGC version initialization failed");
|
||||
expectFailure([] { sceAgcInit(14); });
|
||||
expectFailure([] { sceAgcInit(0xffffffffu); });
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#include <stdexcept>
|
||||
|
||||
extern "C" std::uint64_t APS5_VABI sceAgcDcbContextStateOpGetSize(std::uint32_t operation);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbContextStateAnotherOp(CommandBuffer* buf, std::uint32_t operation);
|
||||
extern "C" std::uint32_t* APS5_VABI sceAgcDcbContextStateOp_0100(CommandBuffer* buf, std::uint32_t operation);
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ void testSizes() {
|
|||
std::array<std::uint32_t, 64> words{};
|
||||
CommandBuffer buffer{words.data(), words.data() + words.size(), words.data(), words.data() + words.size(),
|
||||
nullptr, nullptr, 0};
|
||||
check(sceAgcDcbContextStateAnotherOp(&buffer, operation) == words.data(), "context state op did not start at the cursor");
|
||||
check(sceAgcDcbContextStateOp_0100(&buffer, operation) == words.data(), "context state op did not start at the cursor");
|
||||
const auto written = static_cast<std::uint64_t>(buffer.cursor_up - words.data()) * sizeof(std::uint32_t);
|
||||
check(written == sizes[operation], "context state size differs from the written packets");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <tuple>
|
||||
|
||||
extern "C" int APS5_VABI sceAgcGetDataPacketPayloadRange(SceAgcMemoryRange* range, std::uint32_t* cmd, int type);
|
||||
extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddressUnk(std::uint32_t** addr, std::uint32_t* cmd, int type);
|
||||
extern "C" int APS5_VABI sceAgcGetDataPacketPayloadAddress_0090(std::uint32_t** addr, std::uint32_t* cmd, int type);
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
@ -42,7 +42,7 @@ void testRanges() {
|
|||
check(range.size == size, "payload range size mismatch");
|
||||
check(words[0] == header && words[1] == 0x12345678u, "payload range query modified the packet");
|
||||
std::uint32_t* address = nullptr;
|
||||
check(sceAgcGetDataPacketPayloadAddressUnk(&address, words.data(), type) == 0 && address == range.base,
|
||||
check(sceAgcGetDataPacketPayloadAddress_0090(&address, words.data(), type) == 0 && address == range.base,
|
||||
"payload range base differs from the payload address");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,13 +127,13 @@ std::uint8_t* aligned(std::vector<std::uint8_t>& storage, std::size_t alignment)
|
|||
void testFusion(std::size_t misalignment, std::uint32_t terminator = SSetpcS6) {
|
||||
Halves halves(terminator);
|
||||
SizeAlign size{};
|
||||
check(sceAgcUnknownGetFusedShaderSize(&size, &halves.front, &halves.back) == 0, "fused size query failed");
|
||||
check(sceAgcGetFusedShaderSize_0080(&size, &halves.front, &halves.back) == 0, "fused size query failed");
|
||||
check(size.m_align == 8, "fused shaders are not 256-byte aligned");
|
||||
check(size.m_size > 256 + 255 + halves.back.shader_size + sizeof(Shader), "fused size does not cover the alignment padding, code and header");
|
||||
std::vector<std::uint8_t> storage(size.m_size + 512, 0xcd);
|
||||
auto* scratch = aligned(storage, 256) + misalignment;
|
||||
Shader fused{};
|
||||
check(sceAgcUnknownFuseShaderHalves(&fused, &halves.front, &halves.back, scratch) == 0, "fusion failed");
|
||||
check(sceAgcFuseShaderHalves_0200(&fused, &halves.front, &halves.back, scratch) == 0, "fusion failed");
|
||||
for (std::size_t i = 0; i < 16; ++i) check(scratch[size.m_size + i] == 0xcd, "fusion wrote past the reported size");
|
||||
auto* memory = scratch + (256 - misalignment) % 256;
|
||||
const auto base = reinterpret_cast<std::uintptr_t>(memory);
|
||||
|
|
@ -174,38 +174,38 @@ void testRejections() {
|
|||
Halves halves;
|
||||
SizeAlign size{};
|
||||
Shader fused{};
|
||||
expectFailure([&] { sceAgcUnknownGetFusedShaderSize(nullptr, &halves.front, &halves.back); });
|
||||
expectFailure([&] { sceAgcUnknownFuseShaderHalves(&fused, &halves.front, &halves.back, nullptr); });
|
||||
expectFailure([&] { sceAgcGetFusedShaderSize_0080(nullptr, &halves.front, &halves.back); });
|
||||
expectFailure([&] { sceAgcFuseShaderHalves_0200(&fused, &halves.front, &halves.back, nullptr); });
|
||||
{
|
||||
Halves swapped;
|
||||
check(sceAgcUnknownGetFusedShaderSize(&size, &swapped.back, &swapped.front) == InvalidShaderHalves, "swapped halves were accepted by the size query");
|
||||
check(sceAgcUnknownFuseShaderHalves(&fused, &swapped.back, &swapped.front, nullptr) == InvalidShaderHalves, "swapped halves were fused");
|
||||
check(sceAgcGetFusedShaderSize_0080(&size, &swapped.back, &swapped.front) == InvalidShaderHalves, "swapped halves were accepted by the size query");
|
||||
check(sceAgcFuseShaderHalves_0200(&fused, &swapped.back, &swapped.front, nullptr) == InvalidShaderHalves, "swapped halves were fused");
|
||||
}
|
||||
{
|
||||
Halves stages;
|
||||
stages.backSpecials.vgt_shader_stages_en.value = 0;
|
||||
std::vector<std::uint8_t> storage(4096);
|
||||
check(sceAgcUnknownFuseShaderHalves(&fused, &stages.front, &stages.back, storage.data()) == InvalidShaderHalves, "halves with different GS stages were fused");
|
||||
check(sceAgcFuseShaderHalves_0200(&fused, &stages.front, &stages.back, storage.data()) == InvalidShaderHalves, "halves with different GS stages were fused");
|
||||
}
|
||||
{
|
||||
Halves noJump;
|
||||
noJump.frontCode[2] = SNop;
|
||||
expectFailure([&] { sceAgcUnknownGetFusedShaderSize(&size, &noJump.front, &noJump.back); });
|
||||
expectFailure([&] { sceAgcGetFusedShaderSize_0080(&size, &noJump.front, &noJump.back); });
|
||||
}
|
||||
{
|
||||
Halves noTrailer;
|
||||
noTrailer.frontCode[5] = 0;
|
||||
expectFailure([&] { sceAgcUnknownGetFusedShaderSize(&size, &noTrailer.front, &noTrailer.back); });
|
||||
expectFailure([&] { sceAgcGetFusedShaderSize_0080(&size, &noTrailer.front, &noTrailer.back); });
|
||||
}
|
||||
{
|
||||
Halves hardware;
|
||||
hardware.frontSh[2].value |= 1u << 16u;
|
||||
expectFailure([&] { sceAgcUnknownGetFusedShaderSize(&size, &hardware.front, &hardware.back); });
|
||||
expectFailure([&] { sceAgcGetFusedShaderSize_0080(&size, &hardware.front, &hardware.back); });
|
||||
}
|
||||
{
|
||||
Halves constants;
|
||||
constants.back.embedded_constant_buffer_size_dqw = 1;
|
||||
expectFailure([&] { sceAgcUnknownGetFusedShaderSize(&size, &constants.front, &constants.back); });
|
||||
expectFailure([&] { sceAgcGetFusedShaderSize_0080(&size, &constants.front, &constants.back); });
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -229,10 +229,10 @@ void testHullHalves() {
|
|||
back.specials = &specials;
|
||||
back.type = static_cast<std::uint8_t>(ShaderRegs::ShaderBinaryType::HsBack);
|
||||
SizeAlign size{};
|
||||
check(sceAgcUnknownGetFusedShaderSize(&size, &front, &back) == 0 && size.m_size == backSh.size() * sizeof(ShaderRegister) && size.m_align == 4, "hull size query changed");
|
||||
check(sceAgcGetFusedShaderSize_0080(&size, &front, &back) == 0 && size.m_size == backSh.size() * sizeof(ShaderRegister) && size.m_align == 4, "hull size query changed");
|
||||
std::vector<ShaderRegister> scratch(backSh.size());
|
||||
Shader fused{};
|
||||
check(sceAgcUnknownFuseShaderHalves(&fused, &front, &back, scratch.data()) == 0, "hull fusion failed");
|
||||
check(sceAgcFuseShaderHalves_0200(&fused, &front, &back, scratch.data()) == 0, "hull fusion failed");
|
||||
check(fused.type == static_cast<std::uint8_t>(ShaderRegs::ShaderBinaryType::Hs) && fused.code == back.code && fused.sh_registers == scratch.data() && fused.user_data == nullptr, "hull halves were not fused at the register level");
|
||||
const auto address = reinterpret_cast<std::uint64_t>(front.code);
|
||||
check(scratch[0].value == 0x11u && scratch[1].value == 0x22u, "hull checksums were not taken from the front half");
|
||||
|
|
|
|||
|
|
@ -95,16 +95,14 @@ Throughout the project, every function at every stage either **does exactly what
|
|||
- [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.
|
||||
- [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
|
||||
- [zARR5aCmkoY](../../core/libs/prx/libSceAgc/DcbFlow/src/Control.cpp) (libSceAgc) - unknown name, signature
|
||||
- [qj7QZpgr9Uw](../../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - unknown name
|
||||
- [sceAgcDcbContextStateOpGetSize](../../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - sizes from KytyPS5 only (5, 27, 27 and 32 dwords), equal to what `qj7QZpgr9Uw` writes; KytyPS5 returns 0 for an operation above 3, here it throws
|
||||
- [sceAgcDcbContextStateOpGetSize](../../core/libs/prx/libSceAgc/DcbState/src/ContextState.cpp) (libSceAgc) - sizes from KytyPS5 only (5, 27, 27 and 32 dwords), equal to what `sceAgcDcbContextStateOp_0100` writes; KytyPS5 returns 0 for an operation above 3, here it throws
|
||||
- [sceAgcBranchPatchSetThenTarget_0300, sceAgcBranchPatchSetElseTarget_0300](../../core/libs/prx/libSceAgc/Unimplemented.cpp) (libSceAgc) - names from their NIDs (`7Wa3aeJgeVU`, `rP5xLdOf26k`), signatures unknown
|
||||
- [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
|
||||
- [fd5Bp5tGTgo](../../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - unknown name
|
||||
- [dolOmWH+huQ](../../core/libs/prx/libSceAgc/Misc/src/ShaderFusion.cpp) (libSceAgc) - unknown name
|
||||
- [dbOlWdppb4o](../../core/libs/prx/libSceAgc/Shader/src/InterpolantMapping.cpp) (libSceAgc) - unknown name; same arguments as `sceAgcCreateInterpolantMapping`; the `SPI_PS_INPUT_CNTL` bits for `is_f16` 2 inputs follow KytyPS5, not confirmed on hardware
|
||||
- [V++UgBtQhn0](../../core/libs/prx/libSceAgc/Misc/src/PacketInfo.cpp) (libSceAgc) - unknown name
|
||||
- [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 `V++UgBtQhn0`; prosper returns header + 2 for both types from that address function
|
||||
- [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
|
||||
- [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
|
||||
- [gQkqkLttcpw](../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - unknown name, signature
|
||||
- [sceAgcAcbAtomicGds_0900](../../core/libs/prx/libSceAgc/Acb/src/Control.cpp) (libSceAgc) - name from its NID (`gQkqkLttcpw`), signature unknown
|
||||
- [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)
|
||||
- [sceKernelInternalMemoryGetModuleSegmentInfo](../../core/libs/prx/libkernel/Module/src/Module.cpp) (libkernel) - unknown signature
|
||||
|
|
|
|||
Loading…
Reference in New Issue