#include #include #include "SceTypes.hpp" #include "prx/libc/include/General.hpp" #include "prx/libkernel/Apr/include/AprCommandBuffer.hpp" #include static constexpr int SCE_AMPR_ERROR_BUFFER_FULL = 0x8002001C; static constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016; static int Append(Apr::CommandBufferObject* buffer, const void* command, uint32_t bytes) { if (!buffer->base || bytes > buffer->size - buffer->offset) return SCE_AMPR_ERROR_BUFFER_FULL; std::memcpy(buffer->base + buffer->offset, command, bytes); buffer->offset += bytes; ++buffer->numCommands; return 0; } template static int AppendCommand(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, TCommand command) { if (!buffer) return static_cast(0x80020016); command.header = {opcode, sizeof(command)}; return Append(buffer, &command, sizeof(command)); } static std::uint64_t MarkerBytes(const char* text) { return sizeof(Apr::MarkerCommand) + ((std::strlen(text) + 8) & ~std::uint64_t{7}); } static std::uint64_t MeasureMarker(const char* text) { if (!text) return static_cast(SCE_KERNEL_ERROR_EINVAL); return MarkerBytes(text); } static int AppendMarker(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, const char* text) { if (!buffer || !text) return SCE_KERNEL_ERROR_EINVAL; const std::uint64_t bytes = MarkerBytes(text); if (!buffer->base || bytes > buffer->size - buffer->offset) return SCE_AMPR_ERROR_BUFFER_FULL; const Apr::MarkerCommand command{{opcode, static_cast(bytes)}}; std::uint8_t* destination = buffer->base + buffer->offset; std::memset(destination, 0, bytes); std::memcpy(destination, &command, sizeof(command)); std::memcpy(destination + sizeof(command), text, std::strlen(text)); buffer->offset += static_cast(bytes); ++buffer->numCommands; return 0; } extern "C" { int APS5_VABI sceAmprCommandBufferWriteAddressOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t value) { if (!address) return static_cast(0x80020016); return AppendCommand(buffer, Apr::Opcode::WriteAddress, Apr::WriteAddressCommand{{}, reinterpret_cast(address), value, 0, 0}); } int APS5_VABI sceAmprCommandBufferWriteCounterOnCompletion(Apr::CommandBufferObject* buffer, std::uint32_t counter, std::uint32_t value) { return AppendCommand(buffer, Apr::Opcode::WriteCounter, Apr::WriteCounterCommand{{}, counter, value}); } int APS5_VABI sceAmprCommandBufferWaitOnAddress(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t reference, std::uint64_t mask, std::uint32_t compare) { return AppendCommand(buffer, Apr::Opcode::WaitOnAddress, Apr::WaitCommand{{}, reinterpret_cast(address), reference, mask, 0, compare}); } int APS5_VABI sceAmprCommandBufferWaitOnCounter(Apr::CommandBufferObject* buffer, std::uint32_t counter, std::uint32_t reference, std::uint32_t compare) { return AppendCommand(buffer, Apr::Opcode::WaitOnCounter, Apr::WaitCommand{{}, 0, reference, ~0ull, counter, compare}); } int APS5_VABI sceAmprCommandBufferWriteKernelEventQueueOnCompletion(Apr::CommandBufferObject* buffer, std::uint64_t equeue, std::uint64_t ident, std::uint64_t data, std::uint64_t userData) { return AppendCommand(buffer, Apr::Opcode::WriteKernelEventQueue, Apr::WriteKernelEventQueueCommand{{}, equeue, ident, data, userData}); } int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address) { return AppendCommand(buffer, Apr::Opcode::WriteAddressFromTimeCounter, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast(address), 0, 0}); } int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint32_t counter) { return AppendCommand(buffer, Apr::Opcode::WriteAddressFromCounter, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast(address), counter, 0}); } int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPairOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint32_t counter0, std::uint32_t counter1) { return AppendCommand(buffer, Apr::Opcode::WriteAddressFromCounterPair, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast(address), counter0, counter1}); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressOnCompletion() { return sizeof(Apr::WriteAddressCommand); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteCounterOnCompletion() { return sizeof(Apr::WriteCounterCommand); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnAddress() { return sizeof(Apr::WaitCommand); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnCounter() { return sizeof(Apr::WaitCommand); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteKernelEventQueueOnCompletion() { return sizeof(Apr::WriteKernelEventQueueCommand); } int APS5_VABI sceAmprAprCommandBufferConstructor(Apr::CommandBufferObject* buffer, uint64_t* gatherState, uint64_t* scatterState) { buffer->type = Apr::BufferType::Apr; *gatherState = 0; *scatterState = 0; return 0; } int APS5_VABI sceAmprAprCommandBufferDestructor(Apr::CommandBufferObject* buffer, uint64_t* gatherState, uint64_t* scatterState) { (void)buffer; (void)gatherState; (void)scatterState; return 0; } int APS5_VABI sceAmprAprCommandBufferMapBegin() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprAprCommandBufferMapDirectBegin() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprAprCommandBufferMapEnd() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprAprCommandBufferReadFile(Apr::CommandBufferObject* buffer, uint64_t* gatherState, uint64_t* scatterState, uint32_t fileId, void* destination, uint64_t size, uint64_t offset) { (void)gatherState; (void)scatterState; Apr::ReadFileCommand command{}; command.header = {Apr::Opcode::ReadFile, sizeof(command)}; command.fileId = fileId; command.destination = reinterpret_cast(destination); command.size = size; command.offset = offset; return Append(buffer, &command, sizeof(command)); } int APS5_VABI sceAmprAprCommandBufferReadFileGather() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprAprCommandBufferReadFileGatherScatter() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprAprCommandBufferReadFileScatter() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprAprCommandBufferResetGatherScatterState() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferClearBuffer(Apr::CommandBufferObject* buffer) { buffer->base = nullptr; buffer->size = 0; buffer->offset = 0; buffer->numCommands = 0; return 0; } int APS5_VABI sceAmprCommandBufferConstructMarker() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferConstructNop() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferConstructor(Apr::CommandBufferObject* buffer) { *buffer = {nullptr, 0, 0, 0, Apr::BufferType::Generic}; return 0; } int APS5_VABI sceAmprCommandBufferDestructor(Apr::CommandBufferObject* buffer) { (void)buffer; return 0; } void* APS5_VABI sceAmprCommandBufferGetBufferBaseAddress(const Apr::CommandBufferObject* buffer) { return buffer->base; } uint32_t APS5_VABI sceAmprCommandBufferGetCurrentOffset(const Apr::CommandBufferObject* buffer) { return buffer->offset; } uint32_t APS5_VABI sceAmprCommandBufferGetNumCommands(const Apr::CommandBufferObject* buffer) { return buffer->numCommands; } uint32_t APS5_VABI sceAmprCommandBufferGetSize(const Apr::CommandBufferObject* buffer) { return buffer->size; } uint32_t APS5_VABI sceAmprCommandBufferGetType(const Apr::CommandBufferObject* buffer) { return static_cast(buffer->type); } int APS5_VABI sceAmprCommandBufferNop() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferNopWithData() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferPopMarker(Apr::CommandBufferObject* buffer) { return AppendCommand(buffer, Apr::Opcode::PopMarker, Apr::MarkerCommand{}); } int APS5_VABI sceAmprCommandBufferPushMarker(Apr::CommandBufferObject* buffer, const char* text) { return AppendMarker(buffer, Apr::Opcode::PushMarker, text); } int APS5_VABI sceAmprCommandBufferPushMarkerWithColor(Apr::CommandBufferObject* buffer, const char* text, std::uint32_t color) { (void)color; return AppendMarker(buffer, Apr::Opcode::PushMarker, text); } int APS5_VABI sceAmprCommandBufferReset(Apr::CommandBufferObject* buffer) { buffer->offset = 0; buffer->numCommands = 0; return 0; } int APS5_VABI sceAmprCommandBufferSetBuffer(Apr::CommandBufferObject* buffer, void* memory, uint32_t size) { buffer->base = static_cast(memory); buffer->size = size; buffer->offset = 0; buffer->numCommands = 0; return 0; } int APS5_VABI sceAmprCommandBufferSetMarker(Apr::CommandBufferObject* buffer, const char* text) { return AppendMarker(buffer, Apr::Opcode::SetMarker, text); } int APS5_VABI sceAmprCommandBufferSetMarkerWithColor(Apr::CommandBufferObject* buffer, const char* text, const std::uint32_t* color) { if (!color) return SCE_KERNEL_ERROR_EINVAL; return AppendMarker(buffer, Apr::Opcode::SetMarker, text); } int APS5_VABI sceAmprCommandBufferWaitOnAddress_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferWaitOnCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPair_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferWriteAddressFromCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferWriteAddress_04_00(Apr::CommandBufferObject* buffer, uint64_t* address, uint64_t value, uint32_t flags) { Apr::WriteAddressCommand command{}; command.header = {Apr::Opcode::WriteAddress, sizeof(command)}; command.address = reinterpret_cast(address); command.value = value; command.flags = flags; return Append(buffer, &command, sizeof(command)); } int APS5_VABI sceAmprCommandBufferWriteCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprCommandBufferWriteKernelEventQueue_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeMapBegin() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeMapDirectBegin() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeMapEnd() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeNop() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeNopWithData() { NotImplemented_nid_no_patch(__func__); return 0; } std::uint64_t APS5_VABI sceAmprMeasureCommandSizePopMarker() { return sizeof(Apr::MarkerCommand); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizePushMarker(const char* text) { return MeasureMarker(text); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizePushMarkerWithColor(const char* text, std::uint32_t color) { (void)color; return MeasureMarker(text); } uint32_t APS5_VABI sceAmprMeasureCommandSizeReadFile(void) { return sizeof(Apr::ReadFileCommand); } int APS5_VABI sceAmprMeasureCommandSizeReadFileGather() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeReadFileGatherScatter() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeReadFileScatter() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeResetGatherScatterState() { NotImplemented_nid_no_patch(__func__); return 0; } std::uint64_t APS5_VABI sceAmprMeasureCommandSizeSetMarker(const char* text) { return MeasureMarker(text); } std::uint64_t APS5_VABI sceAmprMeasureCommandSizeSetMarkerWithColor(const char* text, std::uint32_t color) { (void)color; return MeasureMarker(text); } int APS5_VABI sceAmprMeasureCommandSizeWaitOnAddress_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeWaitOnCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounterPair_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromTimeCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } uint32_t APS5_VABI sceAmprMeasureCommandSizeWriteAddress_04_00(void) { return sizeof(Apr::WriteAddressCommand); } int APS5_VABI sceAmprMeasureCommandSizeWriteCounter_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } int APS5_VABI sceAmprMeasureCommandSizeWriteKernelEventQueue_04_00() { NotImplemented_nid_no_patch(__func__); return 0; } }