#include "prx/libScePsml_debug/libScePsml_debug.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include #include namespace { void Require(bool value) { if (!value) std::abort(); } constexpr std::int32_t kErrNotInitialized = static_cast(0x8A810001); using GetDispatchPacket = std::int32_t (APS5_VABI*)(void*, void*, const void*); template void CreateContextUntouched(std::int32_t (APS5_VABI* create)(void**, const TParam*)) { std::array param{}; std::uint64_t contextStorage = 0; void* const sentinel = &contextStorage; void* context = sentinel; Require(create(&context, reinterpret_cast(param.data())) == kErrNotInitialized); Require(context == sentinel); Require(create(nullptr, nullptr) == kErrNotInitialized); } void DispatchPacketUntouched(GetDispatchPacket dispatch) { std::array param{}; std::uint64_t contextStorage = 0; std::array dwords; dwords.fill(0xa5a5a5a5u); const auto untouchedDwords = dwords; MfsrCommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; Require(dispatch(&contextStorage, &commandBuffer, param.data()) == kErrNotInitialized); Require(dispatch(nullptr, &commandBuffer, nullptr) == kErrNotInitialized); Require(commandBuffer.cursor == dwords.data()); Require(commandBuffer.sizeInDwords == dwords.size()); Require(dwords == untouchedDwords); } void SetupBeforeInit() { std::uint64_t storage = 0; void* const sentinel = &storage; void* handle = sentinel; MfsrRequirement requirement{1, 2, 3}; MfsrSharedResourcesParam sharedParam{}; Require(scePsmlMfsrGetSharedResourcesInitRequirement(&requirement, &sharedParam) == kErrNotInitialized); Require(requirement.blockBytes == 1 && requirement.alignment == 2 && requirement.blockCount == 3); Require(scePsmlMfsrCreateSharedResources(&handle, &sharedParam) == kErrNotInitialized); Require(handle == sentinel); Require(scePsmlMfsrReleaseContext(sentinel) == kErrNotInitialized); Require(scePsmlMfsrReleaseSharedResources(sentinel) == kErrNotInitialized); std::uint32_t packetDwords = 0xa5a5a5a5; Require(scePsmlMfsrGetDispatchMfsrPacketSizeInDwords(sentinel, &packetDwords) == kErrNotInitialized); Require(packetDwords == 0xa5a5a5a5); float bias = 0.5f; Require(scePsmlMfsrGetMipmapBias(sentinel, &bias, 3840) == kErrNotInitialized); Require(bias == 0.5f); Require(scePsmlMfsrSelectConfig(sentinel) == kErrNotInitialized); Require(scePsmlMfsrRequestCapture(sentinel) == kErrNotInitialized); Require(scePsmlMfsrIsCaptureInProgress(sentinel) == kErrNotInitialized); } void Mfsr1OnBaseConsole() { constexpr std::int32_t unsupportedConsole = static_cast(0x8A810012); Require(scePsmlMfsrInit() == unsupportedConsole); Require(scePsmlMfsrInit() == unsupportedConsole); SetupBeforeInit(); } void ConcurrentCreatesUninitialized() { std::atomic errors{0}; std::vector pool; for (int i = 0; i < 8; ++i) { pool.emplace_back([&] { for (int round = 0; round < 64; ++round) { MfsrSharedResourcesParam sharedParam{}; void* handle = reinterpret_cast(static_cast(0xdeadbeef)); if (scePsmlMfsrCreateSharedResources(&handle, &sharedParam) != kErrNotInitialized || handle != reinterpret_cast(static_cast(0xdeadbeef))) ++errors; } }); } for (auto& worker : pool) worker.join(); Require(errors == 0); } void Mfsr2OnBaseConsole() { constexpr std::int32_t notInitialized = static_cast(0x8A8A0001); constexpr std::int32_t unsupportedConsole = static_cast(0x8A8A0012); Require(scePsmlMfsr2Init() == unsupportedConsole); Require(scePsmlMfsr2Init() == unsupportedConsole); std::array param{}; std::array requirement; requirement.fill(0xa5); const auto untouchedRequirement = requirement; Require(scePsmlMfsr2GetSharedResourcesInitRequirement(reinterpret_cast(requirement.data()), reinterpret_cast(param.data())) == notInitialized); Require(scePsmlMfsr2GetContextInitRequirement(reinterpret_cast(requirement.data()), reinterpret_cast(param.data())) == notInitialized); Require(requirement == untouchedRequirement); std::uint64_t storage = 0; void* const sentinel = &storage; void* handle = sentinel; Require(scePsmlMfsr2CreateSharedResources(&handle, reinterpret_cast(param.data())) == notInitialized); Require(scePsmlMfsr2CreateContext(&handle, reinterpret_cast(param.data())) == notInitialized); Require(handle == sentinel); Require(scePsmlMfsr2ReleaseContext(sentinel) == notInitialized); Require(scePsmlMfsr2ReleaseSharedResources(sentinel) == notInitialized); std::uint32_t packetDwords = 0xa5a5a5a5; Require(scePsmlMfsr2GetDispatchPacketsSizeInDwords(sentinel, &packetDwords) == notInitialized); Require(packetDwords == 0xa5a5a5a5); std::array dispatchParam{}; std::array dwords; dwords.fill(0xa5a5a5a5u); const auto untouchedDwords = dwords; MfsrCommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; Require(scePsmlMfsr2GetDispatchPackets(sentinel, &commandBuffer, reinterpret_cast(dispatchParam.data())) == notInitialized); Require(commandBuffer.cursor == dwords.data()); Require(commandBuffer.sizeInDwords == dwords.size()); Require(dwords == untouchedDwords); } } int main() { std::array param{}; std::array requirement; requirement.fill(0xa5); const auto untouchedRequirement = requirement; Require(scePsmlMfsrGetContextBufferRequirement1100(requirement.data(), param.data()) == kErrNotInitialized); Require(requirement == untouchedRequirement); Require(scePsmlMfsrGetContextBufferRequirement1100(nullptr, nullptr) == kErrNotInitialized); std::uint64_t contextStorage = 0; void* const sentinel = &contextStorage; void* context = sentinel; Require(scePsmlMfsrCreateContext1100(&context, param.data()) == kErrNotInitialized); Require(context == sentinel); Require(scePsmlMfsrCreateContext1100(nullptr, nullptr) == kErrNotInitialized); std::array dwords; dwords.fill(0xa5a5a5a5u); const auto untouchedDwords = dwords; MfsrCommandBuffer commandBuffer{dwords.data(), static_cast(dwords.size())}; Require(scePsmlMfsrGetDispatchMfsrPacket1100(&contextStorage, &commandBuffer, param.data()) == kErrNotInitialized); Require(commandBuffer.cursor == dwords.data()); Require(commandBuffer.sizeInDwords == dwords.size()); Require(dwords == untouchedDwords); Require(scePsmlMfsrGetDispatchMfsrPacket1100(nullptr, &commandBuffer, param.data()) == kErrNotInitialized); Require(commandBuffer.cursor == dwords.data()); Require(dwords == untouchedDwords); std::array olderRequirement; olderRequirement.fill(0xa5); const auto untouchedOlderRequirement = olderRequirement; Require(scePsmlMfsrGetContextBufferRequirement800M3_2(reinterpret_cast(olderRequirement.data()), reinterpret_cast(param.data())) == kErrNotInitialized); Require(olderRequirement == untouchedOlderRequirement); Require(scePsmlMfsrGetContextBufferRequirement800M3_2(nullptr, nullptr) == kErrNotInitialized); CreateContextUntouched(scePsmlMfsrCreateContext800M3_2); CreateContextUntouched(scePsmlMfsrCreateContext1300); DispatchPacketUntouched(scePsmlMfsrGetDispatchMfsrPacket900); DispatchPacketUntouched(scePsmlMfsrGetDispatchMfsrPacket1000); DispatchPacketUntouched(scePsmlMfsrGetDispatchMfsrPacket1300); SetupBeforeInit(); Mfsr1OnBaseConsole(); Mfsr2OnBaseConsole(); ConcurrentCreatesUninitialized(); }