AnyPS5/core/libs/prx/libSceAmpr/Export.cpp

1033 lines
50 KiB
C++

#include <cstdint>
#include <cstddef>
#include <ctime>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include "prx/libc/include/SonyCrt.hpp"
#include "prx/libkernel/Apr/include/AprCommandBuffer.hpp"
#include "prx/libkernel/Time/include/Time.hpp"
#include <algorithm>
#include <array>
#include <atomic>
#include <cstring>
#include <limits>
#include <stdexcept>
#include <thread>
static constexpr int SCE_AMPR_ERROR_BUFFER_FULL = 0x8002001C;
static constexpr int SCE_KERNEL_ERROR_EINVAL = 0x80020016;
static constexpr int SCE_KERNEL_ERROR_EPERM = 0x80020001;
static constexpr int SCE_KERNEL_ERROR_ESRCH = 0x80020003;
static constexpr int SCE_KERNEL_ERROR_EBUSY = 0x80020010;
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 bool ValidWaitOnCounter_04_00(std::uint32_t access, std::uint32_t compare, std::uint32_t maskOperation, std::uint32_t flush) {
return access < 8u && compare <= 6u && maskOperation < 2u && flush < 2u;
}
static bool ValidWriteCounter_04_00(std::uint32_t counter, std::uint32_t access, std::uint32_t operation) {
return (counter & 0x80u) == 0u && access < 8u && operation < 5u;
}
static constexpr std::uint64_t MeasureInvalid = static_cast<std::uint32_t>(SCE_KERNEL_ERROR_EINVAL);
static bool ValidReadLength(std::uint64_t length) {
return length != 0u && length <= 0x100000000ull;
}
static bool ValidReadOffset(std::uint64_t offset) {
return offset < 0x10000000000ull;
}
static bool ValidRead(const void* destination, std::uint64_t length, std::uint64_t offset) {
constexpr std::uint64_t userLimit = 0xF00000000000ull;
const auto address = reinterpret_cast<std::uint64_t>(destination);
return ValidReadLength(length) && address <= userLimit && length <= userLimit - address && ValidReadOffset(offset);
}
static int AppendRead(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, std::uint32_t fileId, const void* destination, std::uint64_t size, std::uint64_t offset) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (opcode != Apr::Opcode::ReadFile && (buffer->recording & Apr::ScatterGatherValid) == 0u) return SCE_KERNEL_ERROR_EINVAL;
Apr::ReadFileCommand command{{opcode, sizeof(command)}, fileId, 0, reinterpret_cast<std::uint64_t>(destination), size, offset};
const int result = Append(buffer, &command, sizeof(command));
if (result == 0) buffer->recording |= Apr::ScatterGatherValid;
return result;
}
static std::uint64_t NopBytes(std::uint32_t dwords) {
return sizeof(Apr::CommandHeader) + std::uint64_t{dwords} * 4u;
}
static int AppendNop(Apr::CommandBufferObject* buffer, std::uint32_t dwords, const std::uint32_t* data) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
const std::uint64_t bytes = NopBytes(dwords);
if (!buffer->base || bytes > buffer->size - buffer->offset) return SCE_AMPR_ERROR_BUFFER_FULL;
const Apr::CommandHeader header{Apr::Opcode::Nop, static_cast<std::uint32_t>(bytes)};
std::uint8_t* destination = buffer->base + buffer->offset;
std::memset(destination, 0, bytes);
std::memcpy(destination, &header, sizeof(header));
if (data) std::memcpy(destination + sizeof(header), data, std::uint64_t{dwords} * 4u);
buffer->offset += static_cast<std::uint32_t>(bytes);
++buffer->numCommands;
return 0;
}
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;
}
static bool InMap(const Apr::CommandBufferObject* buffer) {
return buffer && (buffer->recording & Apr::MapActive) != 0u;
}
static bool ValidMapRange(std::uint64_t address, std::uint64_t size) {
constexpr std::uint64_t pageMask = 0x3FFFu;
return address != 0u && size != 0u && ((address | size) & pageMask) == 0u && address + size > address;
}
static bool ValidMap(std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t protection) {
return ValidMapRange(address, size) && (directOffset & 0x3FFFu) == 0u && (static_cast<std::uint32_t>(protection) & 0xFFFFFC0Cu) == 0u;
}
static constexpr std::int64_t AmmMeasureInvalid = SCE_KERNEL_ERROR_EINVAL;
static int AppendAmm(Apr::CommandBufferObject* buffer, const void* command, std::uint32_t bytes) {
if (bytes > buffer->size - buffer->offset) return SCE_KERNEL_ERROR_EBUSY;
return Append(buffer, command, bytes);
}
static int RecordAmmMap(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer->base) return SCE_KERNEL_ERROR_EPERM;
if (!ValidMap(address, directOffset, size, protection)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmMapCommand command{{opcode, sizeof(command)}, address, directOffset, size, type, protection};
return AppendAmm(buffer, &command, sizeof(command));
}
static bool ValidAmmProtection(std::int32_t protection) {
return (static_cast<std::uint32_t>(protection) & 0xFFFFFC0Cu) == 0u;
}
static bool ValidRemap(std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection) {
return ValidMapRange(address, size) && ValidMapRange(source, size) && ValidAmmProtection(protection);
}
static bool ValidProtect(std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask) {
return ValidMapRange(address, size) && ValidAmmProtection(protection) && ValidAmmProtection(mask);
}
static int RecordAmmRemap(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer->base) return SCE_KERNEL_ERROR_EPERM;
if (!ValidRemap(address, source, size, protection)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmRemapCommand command{{opcode, sizeof(command)}, address, source, size, protection, 0};
return AppendAmm(buffer, &command, sizeof(command));
}
static int RecordAmmProtect(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer->base) return SCE_KERNEL_ERROR_EPERM;
if (!ValidProtect(address, size, protection, mask)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmProtectCommand command{{opcode, sizeof(command)}, address, size, type, protection, mask, 0};
return AppendAmm(buffer, &command, sizeof(command));
}
static constexpr std::int32_t PrtAllocationMask = 1019;
static int RecordPrt(Apr::CommandBufferObject* buffer, const void* command, std::uint32_t bytes) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (bytes > buffer->size - buffer->offset) return SCE_KERNEL_ERROR_EBUSY;
if (!buffer->base) return SCE_KERNEL_ERROR_EPERM;
return Append(buffer, command, bytes);
}
static int RecordMapBegin(Apr::CommandBufferObject* buffer, Apr::Opcode opcode, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection) {
if (!ValidMap(address, directOffset, size, protection)) return SCE_KERNEL_ERROR_EINVAL;
if (InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
const int result = AppendCommand(buffer, opcode, Apr::AmmMapCommand{{}, address, directOffset, size, type, protection});
if (result == 0) buffer->recording |= Apr::MapActive;
return result;
}
static int RecordWriteKernelEventQueue(Apr::CommandBufferObject* buffer, std::uint64_t equeue, std::int32_t ident, std::uint64_t data, bool completion) {
if (!equeue) return SCE_KERNEL_ERROR_EINVAL;
if (completion && InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
return AppendCommand(buffer, Apr::Opcode::WriteKernelEventQueue, Apr::WriteKernelEventQueueCommand{{}, equeue, static_cast<std::uint64_t>(ident), data, 0});
}
static int RecordWriteAddressFromTimeCounter(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, bool completion) {
if (!ValidWriteAddress(address)) return SCE_KERNEL_ERROR_EINVAL;
if (completion && InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
return AppendCommand(buffer, Apr::Opcode::WriteAddressFromTimeCounter, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast<std::uint64_t>(address), 0, 0});
}
static int RecordWriteAddressFromCounter(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter, bool completion) {
if (!ValidWriteAddress(address) || !ValidCounter(counter)) return SCE_KERNEL_ERROR_EINVAL;
if (completion && InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
return AppendCommand(buffer, Apr::Opcode::WriteAddressFromCounter, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast<std::uint64_t>(address), counter, 0});
}
static int RecordWriteAddressFromCounterPair(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter, bool completion) {
if (!ValidWriteAddress(address) || (counter & 0x81u) != 0u) return SCE_KERNEL_ERROR_EINVAL;
if (completion && InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
return AppendCommand(buffer, Apr::Opcode::WriteAddressFromCounterPair, Apr::WriteAddressFromCounterCommand{{}, reinterpret_cast<std::uint64_t>(address), counter, counter + 1u});
}
struct Xtime {
std::int64_t sec;
std::int64_t nsec;
};
static constexpr int ThrdSuccess = 0;
static constexpr int ThrdError = 4;
static constexpr int GuestClockRealtime = 0;
static constexpr std::int64_t NanosPerSecond = 1000000000;
static constexpr std::int64_t LongestSleepSeconds = 86400;
static std::atomic_flag sharedPtrSpinLock;
extern "C" {
int APS5_VABI pthread_join_nid_postfix(Pthread thread, void** value);
int APS5_VABI wcsrtombs_s_nid_postfix(std::size_t* result, char* destination, std::size_t capacity, const std::uint16_t** source, std::size_t limit, void* state);
int APS5_VABI _Cnd_init_nid_postfix(void** handle);
int SignalCondition_nid_no_patch(void** handle);
}
static KernelTimespec XtimeDeadline(const Xtime& time) {
constexpr auto largest = std::numeric_limits<std::int64_t>::max();
constexpr auto smallest = std::numeric_limits<std::int64_t>::min();
const auto carry = time.nsec / NanosPerSecond;
auto nanos = time.nsec % NanosPerSecond;
auto seconds = time.sec;
if ((carry > 0 && seconds > largest - carry) || (carry < 0 && seconds < smallest - carry)) throw std::overflow_error("_Thrd_sleep: xtime seconds overflow");
seconds += carry;
if (nanos < 0) {
if (seconds == smallest) throw std::overflow_error("_Thrd_sleep: xtime seconds overflow");
nanos += NanosPerSecond;
--seconds;
}
return {seconds, nanos};
}
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;
if (InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
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;
if (InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
return AppendCommand(buffer, Apr::Opcode::WriteCounter, Apr::WriteCounterCommand{{}, counter, Apr::CounterAccess::Size4, Apr::CounterOperation::Store, 0, 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, Apr::CounterAccess::Size4, 0});
}
int APS5_VABI sceAmprCommandBufferWriteKernelEventQueueOnCompletion(Apr::CommandBufferObject* buffer, std::uint64_t equeue, std::int32_t ident, std::uint64_t data) {
return RecordWriteKernelEventQueue(buffer, equeue, ident, data, true);
}
int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address) {
return RecordWriteAddressFromTimeCounter(buffer, address, true);
}
int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter) {
return RecordWriteAddressFromCounter(buffer, address, counter, true);
}
int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPairOnCompletion(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter) {
return RecordWriteAddressFromCounterPair(buffer, address, counter, true);
}
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(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection) {
return RecordMapBegin(buffer, Apr::Opcode::AmmMap, address, 0, size, type, protection);
}
int APS5_VABI sceAmprAprCommandBufferMapDirectBegin(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection) {
return RecordMapBegin(buffer, Apr::Opcode::AmmMapDirect, address, directOffset, size, type, protection);
}
int APS5_VABI sceAmprAprCommandBufferMapEnd(Apr::CommandBufferObject* buffer) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
const int result = AppendCommand(buffer, Apr::Opcode::MapEnd, Apr::MapEndCommand{});
if (result == 0) buffer->recording &= static_cast<std::uint16_t>(~Apr::MapActive);
return result;
}
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;
if (!ValidRead(destination, size, offset)) return SCE_KERNEL_ERROR_EINVAL;
return AppendRead(buffer, Apr::Opcode::ReadFile, fileId, destination, size, offset);
}
int APS5_VABI sceAmprAprCommandBufferReadFileGather(Apr::CommandBufferObject* buffer, std::uint64_t* mapState, std::uint64_t* scatterGatherState, std::uint64_t size, std::uint64_t offset) {
(void)mapState;
(void)scatterGatherState;
if (!ValidReadLength(size) || !ValidReadOffset(offset)) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer || (buffer->recording & Apr::ScatterGatherValid) == 0u) return SCE_KERNEL_ERROR_EINVAL;
const Apr::CompactReadFileGatherCommand command{
static_cast<std::uint32_t>(Apr::Opcode::CompactReadFileGather) | static_cast<std::uint32_t>(offset >> 32u) << 8u,
static_cast<std::uint32_t>(size - 1u), static_cast<std::uint32_t>(offset)};
return Append(buffer, &command, sizeof(command));
}
int APS5_VABI sceAmprAprCommandBufferReadFileGatherScatter(Apr::CommandBufferObject* buffer, std::uint64_t* mapState, std::uint64_t* scatterGatherState, void* destination, std::uint64_t size, std::uint64_t offset) {
(void)mapState;
(void)scatterGatherState;
if (!ValidRead(destination, size, offset)) return SCE_KERNEL_ERROR_EINVAL;
return AppendRead(buffer, Apr::Opcode::ReadFileGatherScatter, 0, destination, size, offset);
}
int APS5_VABI sceAmprAprCommandBufferReadFileScatter(Apr::CommandBufferObject* buffer, std::uint64_t* mapState, std::uint64_t* scatterGatherState, void* destination, std::uint64_t size) {
(void)mapState;
(void)scatterGatherState;
if (!ValidRead(destination, size, 0)) return SCE_KERNEL_ERROR_EINVAL;
return AppendRead(buffer, Apr::Opcode::ReadFileScatter, 0, destination, size, 0);
}
int APS5_VABI sceAmprAprCommandBufferResetGatherScatterState(Apr::CommandBufferObject* buffer) {
const int result = AppendCommand(buffer, Apr::Opcode::ResetGatherScatterState, Apr::ResetGatherScatterStateCommand{});
if (result == 0) buffer->recording &= static_cast<std::uint16_t>(~Apr::ScatterGatherValid);
return result;
}
void* APS5_VABI sceAmprCommandBufferClearBuffer(Apr::CommandBufferObject* buffer) {
void* memory = buffer->base;
buffer->base = nullptr;
buffer->size = 0;
buffer->offset = 0;
buffer->numCommands = 0;
return memory;
}
int APS5_VABI sceAmprCommandBufferConstructMarker(Apr::CommandBufferObject* buffer, std::uint32_t type, const char* text, const std::uint32_t* color) {
switch (type) {
case 1: return AppendMarker(buffer, Apr::Opcode::SetMarker, text);
case 2: return AppendMarker(buffer, Apr::Opcode::PushMarker, text);
case 3: return AppendCommand(buffer, Apr::Opcode::PopMarker, Apr::MarkerCommand{});
case 5: return color ? AppendMarker(buffer, Apr::Opcode::SetMarker, text) : SCE_KERNEL_ERROR_EINVAL;
case 6: return color ? AppendMarker(buffer, Apr::Opcode::PushMarker, text) : SCE_KERNEL_ERROR_EINVAL;
default: return SCE_KERNEL_ERROR_EINVAL;
}
}
int APS5_VABI sceAmprCommandBufferConstructNop(Apr::CommandBufferObject* buffer, std::int16_t type, const void* payload, std::uint32_t payloadBytes, const std::uint32_t* word) {
(void)type;
if (payloadBytes > (word ? 56u : 60u)) return SCE_KERNEL_ERROR_EINVAL;
if (payloadBytes != 0u && !payload) throw std::invalid_argument("sceAmprCommandBufferConstructNop: null payload");
const std::uint32_t dwords = (payloadBytes + 3u) / 4u + (word ? 1u : 0u);
const std::uint32_t offset = buffer ? buffer->offset : 0u;
const int result = AppendNop(buffer, dwords, nullptr);
if (result != 0) return result;
std::uint8_t* data = buffer->base + offset + sizeof(Apr::CommandHeader);
if (word) {
std::memcpy(data, word, sizeof(*word));
data += sizeof(*word);
}
if (payloadBytes != 0u) std::memcpy(data, payload, payloadBytes);
return 0;
}
int APS5_VABI sceAmprCommandBufferConstructor(Apr::CommandBufferObject* buffer) {
*buffer = {Apr::BufferType::Generic, 0, 0, 0, 0, nullptr};
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(Apr::CommandBufferObject* buffer, std::uint32_t dwords) {
if (dwords == 0u || dwords > 16u) return SCE_KERNEL_ERROR_EINVAL;
return AppendNop(buffer, dwords, nullptr);
}
int APS5_VABI sceAmprCommandBufferNopWithData(Apr::CommandBufferObject* buffer, std::uint32_t dwords, const std::uint32_t* data) {
if (dwords > 15u) return SCE_KERNEL_ERROR_EINVAL;
if (dwords != 0u && !data) throw std::invalid_argument("sceAmprCommandBufferNopWithData: null data");
return AppendNop(buffer, dwords, data);
}
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(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t reference, std::uint8_t compare, std::uint8_t flush) {
if (!ValidWriteAddress(address) || compare > 6u || flush > 1u) 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_04_00(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint8_t access, std::uint64_t reference, std::uint8_t compare, std::uint8_t maskOperation, std::uint64_t mask, std::uint8_t flush) {
if (!ValidWaitOnCounter_04_00(access, compare, maskOperation, flush)) return SCE_KERNEL_ERROR_EINVAL;
const std::uint64_t applied = maskOperation ? mask : ~0ull;
return AppendCommand(buffer, Apr::Opcode::WaitOnCounter, Apr::WaitCommand{{}, 0, reference, applied, counter, compare, static_cast<Apr::CounterAccess>(access), 0});
}
int APS5_VABI sceAmprCommandBufferWriteAddressFromCounterPair_04_00(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter, std::uint64_t atStart) {
return RecordWriteAddressFromCounterPair(buffer, address, counter, atStart == 0u);
}
int APS5_VABI sceAmprCommandBufferWriteAddressFromCounter_04_00(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint8_t counter, std::uint64_t atStart) {
return RecordWriteAddressFromCounter(buffer, address, counter, atStart == 0u);
}
int APS5_VABI sceAmprCommandBufferWriteAddressFromTimeCounter_04_00(Apr::CommandBufferObject* buffer, volatile std::uint64_t* address, std::uint64_t atStart) {
return RecordWriteAddressFromTimeCounter(buffer, address, atStart == 0u);
}
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(Apr::CommandBufferObject* buffer, std::uint8_t counter, std::uint8_t access, std::uint64_t value, std::uint8_t operation, std::uint8_t atStart) {
if (!ValidWriteCounter_04_00(counter, access, operation)) return SCE_KERNEL_ERROR_EINVAL;
if (atStart == 0u && InMap(buffer)) return SCE_KERNEL_ERROR_EPERM;
return AppendCommand(buffer, Apr::Opcode::WriteCounter, Apr::WriteCounterCommand{{}, counter, static_cast<Apr::CounterAccess>(access), static_cast<Apr::CounterOperation>(operation), 0, value});
}
int APS5_VABI sceAmprCommandBufferWriteKernelEventQueue_04_00(Apr::CommandBufferObject* buffer, std::uint64_t equeue, std::int32_t ident, std::uint64_t data, std::uint64_t atStart) {
return RecordWriteKernelEventQueue(buffer, equeue, ident, data, atStart == 0u);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapBegin(std::uint64_t address, std::uint64_t size, std::uint32_t type, std::uint32_t protection) {
(void)type;
if (!ValidMap(address, 0, size, static_cast<std::int32_t>(protection))) return MeasureInvalid;
return sizeof(Apr::AmmMapCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapDirectBegin(std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::uint32_t type, std::uint32_t protection) {
(void)type;
if (!ValidMap(address, directOffset, size, static_cast<std::int32_t>(protection))) return MeasureInvalid;
return sizeof(Apr::AmmMapCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeMapEnd() {
return sizeof(Apr::MapEndCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeNop(std::uint32_t dwords) {
if (dwords == 0u || dwords > 16u) return MeasureInvalid;
return NopBytes(dwords);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeNopWithData(std::uint32_t dwords) {
if (dwords == 0u || dwords > 16u) return MeasureInvalid;
return NopBytes(dwords - 1u);
}
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);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileGather(std::uint64_t size, std::uint64_t offset) {
if (!ValidReadLength(size) || !ValidReadOffset(offset)) return MeasureInvalid;
return sizeof(Apr::CompactReadFileGatherCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileGatherScatter(void* destination, std::uint64_t size, std::uint64_t offset) {
if (!ValidRead(destination, size, offset)) return MeasureInvalid;
return sizeof(Apr::ReadFileCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeReadFileScatter(void* destination, std::uint64_t size) {
if (!ValidRead(destination, size, 0)) return MeasureInvalid;
return sizeof(Apr::ReadFileCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeResetGatherScatterState() {
return sizeof(Apr::ResetGatherScatterStateCommand);
}
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);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnAddress_04_00(volatile std::uint64_t* address, std::uint64_t, std::uint8_t compare, std::uint8_t flush) {
if (!ValidWriteAddress(address) || compare > 6u || flush > 1u) return MeasureInvalid;
return sizeof(Apr::WaitCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWaitOnCounter_04_00(std::uint8_t, std::uint8_t access, std::uint64_t, std::uint8_t compare, std::uint8_t maskOperation, std::uint64_t, std::uint8_t flush) {
if (!ValidWaitOnCounter_04_00(access, compare, maskOperation, flush)) return MeasureInvalid;
return sizeof(Apr::WaitCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounterPair_04_00(volatile std::uint64_t* address, std::uint8_t counter) {
if (!ValidWriteAddress(address) || (counter & 1u) != 0u) return MeasureInvalid;
return sizeof(Apr::WriteAddressFromCounterCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromCounter_04_00(volatile std::uint64_t* address, std::uint8_t counter) {
(void)counter;
if (!ValidWriteAddress(address)) return MeasureInvalid;
return sizeof(Apr::WriteAddressFromCounterCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteAddressFromTimeCounter_04_00(volatile std::uint64_t* address) {
if (!ValidWriteAddress(address)) return MeasureInvalid;
return sizeof(Apr::WriteAddressFromCounterCommand);
}
uint32_t APS5_VABI sceAmprMeasureCommandSizeWriteAddress_04_00(void) {
return sizeof(Apr::WriteAddressCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteCounter_04_00(std::uint8_t counter, std::uint8_t access, std::uint64_t, std::uint8_t operation) {
if (!ValidWriteCounter_04_00(counter, access, operation)) return MeasureInvalid;
return sizeof(Apr::WriteCounterCommand);
}
std::uint64_t APS5_VABI sceAmprMeasureCommandSizeWriteKernelEventQueue_04_00(std::uint64_t, std::int32_t, std::uint64_t) {
return sizeof(Apr::WriteKernelEventQueueCommand);
}
struct AmmSubmitResult {
std::int32_t result;
std::uint32_t errorOffset;
};
int APS5_VABI sceAmprAmmCommandBufferConstructor(Apr::CommandBufferObject* buffer) {
(void)buffer;
return 0;
}
int APS5_VABI sceAmprAmmCommandBufferDestructor(Apr::CommandBufferObject* buffer) {
(void)buffer;
return 0;
}
int APS5_VABI sceAmprAmmCommandBufferMap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection) {
return RecordAmmMap(buffer, Apr::Opcode::AmmMap, address, 0, size, type, protection);
}
int APS5_VABI sceAmprAmmCommandBufferMapWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return RecordAmmMap(buffer, Apr::Opcode::AmmMap, address, 0, size, type, protection);
}
int APS5_VABI sceAmprAmmCommandBufferMapDirect(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection) {
return RecordAmmMap(buffer, Apr::Opcode::AmmMapDirect, address, directOffset, size, type, protection);
}
int APS5_VABI sceAmprAmmCommandBufferMapDirectWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return RecordAmmMap(buffer, Apr::Opcode::AmmMapDirect, address, directOffset, size, type, protection);
}
int APS5_VABI sceAmprAmmCommandBufferUnmap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer->base) return SCE_KERNEL_ERROR_EPERM;
if (!ValidMapRange(address, size)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmUnmapCommand command{{Apr::Opcode::AmmUnmap, sizeof(command)}, address, size};
return AppendAmm(buffer, &command, sizeof(command));
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMap(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection) {
(void)type;
return ValidMap(address, 0, size, protection) ? std::int64_t{sizeof(Apr::AmmMapCommand)} : AmmMeasureInvalid;
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapWithGpuMaskId(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return sceAmprAmmMeasureAmmCommandSizeMap(address, size, type, protection);
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapDirect(std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection) {
(void)type;
return ValidMap(address, directOffset, size, protection) ? std::int64_t{sizeof(Apr::AmmMapCommand)} : AmmMeasureInvalid;
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapDirectWithGpuMaskId(std::uint64_t address, std::uint64_t directOffset, std::uint64_t size, std::int32_t type, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return sceAmprAmmMeasureAmmCommandSizeMapDirect(address, directOffset, size, type, protection);
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeUnmap(std::uint64_t address, std::uint64_t size) {
return ValidMapRange(address, size) ? std::int64_t{sizeof(Apr::AmmUnmapCommand)} : AmmMeasureInvalid;
}
int APS5_VABI sceAmprAmmCommandBufferRemap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection) {
return RecordAmmRemap(buffer, Apr::Opcode::AmmRemap, address, source, size, protection);
}
int APS5_VABI sceAmprAmmCommandBufferRemapWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return RecordAmmRemap(buffer, Apr::Opcode::AmmRemap, address, source, size, protection);
}
int APS5_VABI sceAmprAmmCommandBufferMultiMap(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection) {
return RecordAmmRemap(buffer, Apr::Opcode::AmmMultiMap, address, alias, size, protection);
}
int APS5_VABI sceAmprAmmCommandBufferMultiMapWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return RecordAmmRemap(buffer, Apr::Opcode::AmmMultiMap, address, alias, size, protection);
}
int APS5_VABI sceAmprAmmCommandBufferModifyProtect(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask) {
return RecordAmmProtect(buffer, Apr::Opcode::AmmModifyProtect, address, size, 0, protection, mask);
}
int APS5_VABI sceAmprAmmCommandBufferModifyProtectWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return RecordAmmProtect(buffer, Apr::Opcode::AmmModifyProtect, address, size, 0, protection, mask);
}
int APS5_VABI sceAmprAmmCommandBufferModifyMtypeProtect(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask) {
return RecordAmmProtect(buffer, Apr::Opcode::AmmModifyMtypeProtect, address, size, type, protection, mask);
}
int APS5_VABI sceAmprAmmCommandBufferModifyMtypeProtectWithGpuMaskId(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return RecordAmmProtect(buffer, Apr::Opcode::AmmModifyMtypeProtect, address, size, type, protection, mask);
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeRemap(std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection) {
return ValidRemap(address, source, size, protection) ? std::int64_t{sizeof(Apr::AmmRemapCommand)} : AmmMeasureInvalid;
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeRemapWithGpuMaskId(std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return sceAmprAmmMeasureAmmCommandSizeRemap(address, source, size, protection);
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMultiMap(std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection) {
return ValidRemap(address, alias, size, protection) ? std::int64_t{sizeof(Apr::AmmRemapCommand)} : AmmMeasureInvalid;
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMultiMapWithGpuMaskId(std::uint64_t address, std::uint64_t alias, std::uint64_t size, std::int32_t protection, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return sceAmprAmmMeasureAmmCommandSizeMultiMap(address, alias, size, protection);
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyProtect(std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask) {
return ValidProtect(address, size, protection, mask) ? std::int64_t{sizeof(Apr::AmmProtectCommand)} : AmmMeasureInvalid;
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyProtectWithGpuMaskId(std::uint64_t address, std::uint64_t size, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return sceAmprAmmMeasureAmmCommandSizeModifyProtect(address, size, protection, mask);
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyMtypeProtect(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask) {
(void)type;
return ValidProtect(address, size, protection, mask) ? std::int64_t{sizeof(Apr::AmmProtectCommand)} : AmmMeasureInvalid;
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeModifyMtypeProtectWithGpuMaskId(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection, std::int32_t mask, std::uint8_t gpuMaskId) {
(void)gpuMaskId;
return sceAmprAmmMeasureAmmCommandSizeModifyMtypeProtect(address, size, type, protection, mask);
}
int APS5_VABI sceAmprAmmCommandBufferMapAsPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!ValidMapRange(address, size)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmUnmapCommand command{{Apr::Opcode::AmmMapAsPrt, sizeof(command)}, address, size};
return RecordPrt(buffer, &command, sizeof(command));
}
int APS5_VABI sceAmprAmmCommandBufferAllocatePaForPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection) {
if (!ValidAmmProtection(protection)) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!ValidMapRange(address, size)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmProtectCommand command{{Apr::Opcode::AmmAllocatePaForPrt, sizeof(command)}, address, size, type, protection, PrtAllocationMask, 0};
return RecordPrt(buffer, &command, sizeof(command));
}
int APS5_VABI sceAmprAmmCommandBufferRemapIntoPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t source, std::uint64_t size, std::int32_t protection, std::uint32_t opcode) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer->base) return SCE_KERNEL_ERROR_EPERM;
if (!ValidRemap(address, source, size, protection)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmRemapCommand command{{Apr::Opcode::AmmRemapIntoPrt, sizeof(command)}, address, source, size, protection, static_cast<std::int32_t>(opcode ? opcode : 1011u)};
return AppendAmm(buffer, &command, sizeof(command));
}
int APS5_VABI sceAmprAmmCommandBufferUnmapToPrt(Apr::CommandBufferObject* buffer, std::uint64_t address, std::uint64_t size) {
if (!buffer) return SCE_KERNEL_ERROR_EINVAL;
if (!buffer->base) return SCE_KERNEL_ERROR_EPERM;
if (!ValidMapRange(address, size)) return SCE_KERNEL_ERROR_EINVAL;
const Apr::AmmUnmapCommand command{{Apr::Opcode::AmmUnmapToPrt, sizeof(command)}, address, size};
return AppendAmm(buffer, &command, sizeof(command));
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeMapAsPrt(std::uint64_t address, std::uint64_t size) {
return ValidMapRange(address, size) ? std::int64_t{sizeof(Apr::AmmUnmapCommand)} : AmmMeasureInvalid;
}
std::int64_t APS5_VABI sceAmprAmmMeasureAmmCommandSizeAllocatePaForPrt(std::uint64_t address, std::uint64_t size, std::int32_t type, std::int32_t protection) {
(void)type;
return ValidMapRange(address, size) && ValidAmmProtection(protection) ? std::int64_t{sizeof(Apr::AmmProtectCommand)} : AmmMeasureInvalid;
}
int APS5_VABI sceAmprAmmGiveDirectMemory(std::int64_t searchStart, std::int64_t searchEnd, std::size_t size, std::size_t alignment, int usage, std::int64_t* offset) {
return AmmGiveDirectMemory_nid_no_patch(searchStart, searchEnd, size, alignment, usage, offset);
}
int APS5_VABI sceAmprAmmGetVirtualAddressRanges(std::uint64_t* start, std::uint64_t* end, std::uint64_t* multimapStart, std::uint64_t* multimapEnd) {
if (!start || !end || !multimapStart || !multimapEnd) throw std::invalid_argument("sceAmprAmmGetVirtualAddressRanges: null output");
AmmVirtualAddressRanges_nid_no_patch(start, end, multimapStart, multimapEnd);
return 0;
}
int APS5_VABI sceAmprAmmSubmitCommandBuffer(void* base, std::uint32_t offset, std::uint32_t priority) {
if (priority > 2u) return SCE_KERNEL_ERROR_EINVAL;
if (!base) return SCE_KERNEL_ERROR_EPERM;
AmmSubmit_nid_no_patch(base, offset);
return 0;
}
int APS5_VABI sceAmprAmmSubmitCommandBuffer2(void* base, std::uint32_t offset, std::uint32_t priority, AmmSubmitResult* result, std::uint32_t* id) {
if (priority > 2u) return SCE_KERNEL_ERROR_EINVAL;
if (!base) return SCE_KERNEL_ERROR_EPERM;
const auto submitted = AmmSubmit_nid_no_patch(base, offset);
if (result) *result = {0, 0};
if (id) *id = submitted;
return 0;
}
int APS5_VABI sceAmprAmmSubmitCommandBuffer3(void* base, std::uint32_t offset, std::uint32_t priority, std::uint32_t* id) {
if (priority > 2u) return SCE_KERNEL_ERROR_EINVAL;
if (!base) return SCE_KERNEL_ERROR_EPERM;
const auto submitted = AmmSubmit_nid_no_patch(base, offset);
if (id) *id = submitted;
return 0;
}
int APS5_VABI sceAmprAmmWaitCommandBufferCompletion(std::uint32_t id) {
return AmmSubmitted_nid_no_patch(id) ? 0 : SCE_KERNEL_ERROR_ESRCH;
}
int APS5_VABI _ZNSt8ios_base7_AddstdEPS__nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZSt16_Throw_Cpp_errori_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _Thrd_join_nid_postfix(Pthread thread, int* code) {
void* result = nullptr;
if (pthread_join_nid_postfix(thread, &result) != 0) return ThrdError;
if (code) *code = static_cast<int>(reinterpret_cast<std::intptr_t>(result));
return ThrdSuccess;
}
int APS5_VABI _ZNSt4_Pad8_ReleaseEv_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNSt4_PadC2Ev_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNSt4_PadD2Ev_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _Thrd_id_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNSt4_Pad7_LaunchEPP7pthread_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _Cnd_signal_nid_postfix(void** handle) {
return SignalCondition_nid_no_patch(handle);
}
void APS5_VABI _Unlock_shared_ptr_spin_lock_nid_postfix(void) {
sharedPtrSpinLock.clear(std::memory_order_release);
}
int APS5_VABI _Cnd_init_with_name_nid_postfix(void** handle, const char*) {
return _Cnd_init_nid_postfix(handle);
}
int APS5_VABI _ZTVN10__cxxabiv120__function_type_infoE_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZTVSt7num_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNKSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE3getES3_S3_RSt8ios_baseRNSt5_IosbIiE8_IostateEP2tmPKcSE__nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE2idE_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZTVN10__cxxabiv119__pointer_type_infoE_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNSt8time_getIcSt19istreambuf_iteratorIcSt11char_traitsIcEEE7_GetcatEPPKNSt6locale5facetEPKS5__nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
void APS5_VABI _Lock_shared_ptr_spin_lock_nid_postfix(void) {
while (sharedPtrSpinLock.test_and_set(std::memory_order_acquire)) std::this_thread::yield();
}
int APS5_VABI _Thrd_sleep_nid_postfix(const Xtime* target, Xtime*) {
if (!target) APS5_INVALID_ARG_EX;
const auto deadline = XtimeDeadline(*target);
for (;;) {
KernelTimespec now{};
if (clock_gettime_nid_postfix(GuestClockRealtime, &now) != 0) throw std::runtime_error("_Thrd_sleep: reading the realtime clock failed");
if (now.tv_sec > deadline.tv_sec || (now.tv_sec == deadline.tv_sec && now.tv_nsec >= deadline.tv_nsec)) return 0;
KernelTimespec remaining{deadline.tv_sec - now.tv_sec, deadline.tv_nsec - now.tv_nsec};
if (remaining.tv_nsec < 0) {
remaining.tv_nsec += NanosPerSecond;
--remaining.tv_sec;
}
remaining.tv_sec = std::min(remaining.tv_sec, LongestSleepSeconds);
if (nanosleep_nid_postfix(&remaining, nullptr) != 0) throw std::runtime_error("_Thrd_sleep: nanosleep failed");
}
}
int APS5_VABI wcstombs_s_nid_postfix(std::size_t* result, char* destination, std::size_t capacity, const std::uint16_t* source, std::size_t limit) {
std::array<std::uint64_t, 16> state{};
return wcsrtombs_s_nid_postfix(result, destination, capacity, &source, limit, state.data());
}
int APS5_VABI __cxa_call_unexpected_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("0hlfW1O4Aa4", sceAmprLocaleconv);
SonyLconv* APS5_VABI sceAmprLocaleconv(void) {
return SonyLocaleconv();
}
APS5_EXPORT("802pFCwC9w0", sceAmprUdivti3);
unsigned __int128 APS5_VABI sceAmprUdivti3(unsigned __int128 dividend, unsigned __int128 divisor) {
return SonyUdivti3(dividend, divisor);
}
APS5_EXPORT("MU25eqxSDTw", sceAmprSinh);
double APS5_VABI sceAmprSinh(double x, double y) {
return SonySinh(x, y);
}
APS5_EXPORT("-vXEQdRADLI", sceAmprStrtokS);
char* APS5_VABI sceAmprStrtokS(char* str, const char* delim, char** context) {
return SonyStrtokS(str, delim, context);
}
APS5_EXPORT("2UFh+YKfuzk", sceAmprCtimeS);
int APS5_VABI sceAmprCtimeS(char* buffer, std::size_t size, const std::int64_t* time) {
return SonyCtimeS(buffer, size, time);
}
APS5_EXPORT("6f5f-qx4ucA", sceAmprWcscpyS);
int APS5_VABI sceAmprWcscpyS(std::uint16_t* dest, std::size_t size, const std::uint16_t* src) {
return SonyWcscpyS(dest, size, src);
}
APS5_EXPORT("ENLfKJEZTjE", sceAmprSetConstraintHandlerS);
void* APS5_VABI sceAmprSetConstraintHandlerS(void* handler) {
return SonySetConstraintHandlerS(handler);
}
APS5_EXPORT("Jo9ON-AX9eU", sceAmprFltrounds);
int APS5_VABI sceAmprFltrounds(void) {
return SonyFltrounds();
}
APS5_EXPORT("ODGONXcSmz4", sceAmprIgnoreHandlerS);
void APS5_VABI sceAmprIgnoreHandlerS(const char* message, void* pointer, int error) {
SonyIgnoreHandlerS(message, pointer, error);
}
APS5_EXPORT("VUzjXknPPBs", sceAmprMbstowcs);
std::size_t APS5_VABI sceAmprMbstowcs(std::uint16_t* dest, const char* src, std::size_t size) {
return SonyMbstowcs(dest, src, size);
}
APS5_EXPORT("qPe7-h5Jnuc", sceAmprAsctimeS);
int APS5_VABI sceAmprAsctimeS(char* buffer, std::size_t size, const GuestTm* time) {
return SonyAsctimeS(buffer, size, time);
}
APS5_EXPORT("qlWiRfOJx1A", sceAmprFpclassifyd);
int APS5_VABI sceAmprFpclassifyd(double value) {
return SonyFpclassifyd(value);
}
}