419 lines
14 KiB
C++
419 lines
14 KiB
C++
#include <cstdint>
|
|
#include <cstddef>
|
|
#include "SceTypes.hpp"
|
|
#include "prx/libc/include/General.hpp"
|
|
#include "prx/libkernel/Apr/include/AprCommandBuffer.hpp"
|
|
#include <cstring>
|
|
|
|
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<class TCommand>
|
|
static int AppendCommand(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, TCommand command) {
|
|
if (!buffer) return static_cast<int>(0x80020016);
|
|
command.header = {opcode, sizeof(command)};
|
|
return Append(buffer, &command, sizeof(command));
|
|
}
|
|
|
|
static bool ValidCounter(std::uint32_t counter) {
|
|
return counter < 128u;
|
|
}
|
|
|
|
static bool ValidWriteAddress(volatile std::uint64_t* address) {
|
|
return address && (reinterpret_cast<std::uintptr_t>(address) & 7u) == 0u;
|
|
}
|
|
|
|
static bool ValidWait(std::uint32_t compare, std::uint32_t flush) {
|
|
return compare < 4u && flush < 2u;
|
|
}
|
|
|
|
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<std::uint32_t>(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<std::uint32_t>(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<std::uint32_t>(bytes);
|
|
++buffer->numCommands;
|
|
return 0;
|
|
}
|
|
|
|
extern "C" {
|
|
|
|
int APS5_VABI sceAmprCommandBufferWriteAddressOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t value) {
|
|
if (!ValidWriteAddress(address)) return SCE_KERNEL_ERROR_EINVAL;
|
|
return AppendCommand(buffer, Apr::Opcode::WriteAddress, Apr::WriteAddressCommand{{}, reinterpret_cast<std::uint64_t>(address), value, 0, 0});
|
|
}
|
|
|
|
int APS5_VABI sceAmprCommandBufferWriteCounterOnCompletion(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint32_t value) {
|
|
if (!ValidCounter(counter)) return SCE_KERNEL_ERROR_EINVAL;
|
|
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::uint8_t compare, std::uint8_t flush) {
|
|
if ((reinterpret_cast<std::uintptr_t>(address) & 7u) != 0u || !ValidWait(compare, flush)) return SCE_KERNEL_ERROR_EINVAL;
|
|
return AppendCommand(buffer, Apr::Opcode::WaitOnAddress, Apr::WaitCommand{{}, reinterpret_cast<std::uint64_t>(address), reference, ~0ull, 0, compare});
|
|
}
|
|
|
|
int APS5_VABI sceAmprCommandBufferWaitOnCounter(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint32_t reference, std::uint8_t compare, std::uint8_t flush) {
|
|
if (!ValidCounter(counter) || !ValidWait(compare, flush)) return SCE_KERNEL_ERROR_EINVAL;
|
|
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::int32_t ident, std::uint64_t data) {
|
|
if (!equeue) return SCE_KERNEL_ERROR_EINVAL;
|
|
return AppendCommand(buffer, Apr::Opcode::WriteKernelEventQueue, Apr::WriteKernelEventQueueCommand{{}, equeue, static_cast<std::uint64_t>(ident), data, 0});
|
|
}
|
|
|
|
int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address) {
|
|
if (!ValidWriteAddress(address)) return SCE_KERNEL_ERROR_EINVAL;
|
|
return AppendCommand(buffer, Apr::Opcode::WriteAddressFromTimeCounter, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast<std::uint64_t>(address), 0, 0});
|
|
}
|
|
|
|
int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter) {
|
|
if (!ValidWriteAddress(address) || !ValidCounter(counter)) return SCE_KERNEL_ERROR_EINVAL;
|
|
return AppendCommand(buffer, Apr::Opcode::WriteAddressFromCounter, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast<std::uint64_t>(address), counter, 0});
|
|
}
|
|
|
|
int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPairOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter) {
|
|
if (!ValidWriteAddress(address) || (counter & 0x81u) != 0u) return SCE_KERNEL_ERROR_EINVAL;
|
|
return AppendCommand(buffer, Apr::Opcode::WriteAddressFromCounterPair, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast<std::uint64_t>(address), counter, counter + 1u});
|
|
}
|
|
|
|
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<uint64_t>(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<uint32_t>(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<uint8_t*>(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<uint64_t>(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;
|
|
}
|
|
|
|
}
|