feat(libs): agc packet builders, savedata memory, offline service stubs

- libSceAgc: SetIndexCount, SetBaseIndirectArgs, DispatchIndirect, wait
  and write-data patch functions, relaxed checks for what titles send,
  NOP fillers for LOD stats and wait-until-safe, NotImplemented stubs.
- libSceSaveData.native: short mount points, backup events, save-data
  memory slots.
- user/system service, store dialog, video-out flip modes and queue-full
  error, pad read, fibers, offline behaviour for network/NP modules, and
  new export-only modules Ampr, JpegEnc, Json2, MsgDialog.native,
  NpCppWebApi, NpUtility.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177gthrWEBBfBu5xJDXgBfo
This commit is contained in:
devilismyfriend 2026-09-25 16:27:49 -07:00
parent 91557ebade
commit 9c2a75601d
57 changed files with 3328 additions and 939 deletions

View File

@ -2,47 +2,55 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
// Audio co-processor batches complete immediately without producing output; audio is silent.
static constexpr int SCE_ACM_ERROR_INVALID_PARAMETER = static_cast<int>(0x80E30002);
static std::atomic<uint32_t> g_nextId{1};
extern "C" {
int APS5_VABI sceAcmBatchStartBuffer(AcmContextId context, const void* batch_commands, size_t batch_size, AcmBatchError* batch_error, AcmBatchId* batch) {
(void)context;
(void)batch_commands;
(void)batch_size;
(void)batch_error;
(void)batch;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)context;
(void)batch_commands;
(void)batch_size;
(void)batch_error;
if (!batch) return SCE_ACM_ERROR_INVALID_PARAMETER;
*batch = g_nextId.fetch_add(1, std::memory_order_relaxed);
return 0;
}
int APS5_VABI sceAcmBatchStartBuffers(AcmContextId context, uint32_t batch_info_count, const AcmBatchInfo* const batch_info[], AcmBatchError* batch_error, AcmBatchId* batch) {
(void)context;
(void)batch_info_count;
(void)batch_info;
(void)batch_error;
(void)batch;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)context;
(void)batch_info_count;
(void)batch_info;
(void)batch_error;
if (!batch) return SCE_ACM_ERROR_INVALID_PARAMETER;
*batch = g_nextId.fetch_add(1, std::memory_order_relaxed);
return 0;
}
int APS5_VABI sceAcmBatchWait(AcmContextId context, AcmBatchId batch, uint32_t timeout) {
(void)context;
(void)batch;
(void)timeout;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)context;
(void)batch;
(void)timeout;
return 0;
}
int APS5_VABI sceAcmContextCreate(AcmContextId* context) {
(void)context;
NotImplemented_nid_no_patch(__func__);
return 0;
if (!context) return SCE_ACM_ERROR_INVALID_PARAMETER;
*context = g_nextId.fetch_add(1, std::memory_order_relaxed);
return 0;
}
int APS5_VABI sceAcmContextDestroy(AcmContextId context) {
(void)context;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)context;
return 0;
}
// Builds a convolution-reverb command into a batch; batches execute as no-ops, so nothing is encoded.
int APS5_VABI sceAcm_ConvReverb_SharedInput(void) {
return 0;
}
}

View File

@ -30,11 +30,16 @@ uint32_t APS5_VABI sceAgcAcbJumpGetSize(void) {
return 0;
}
uint32_t* APS5_VABI sceAgcAcbResetQueue(CommandBuffer* buf, uint32_t op) {
(void)buf;
(void)op;
NotImplemented_nid_no_patch(__func__);
return nullptr;
// Encoded as the custom DISPATCH_RESET NOP packet the driver consumes on compute queues.
uint32_t* APS5_VABI sceAgcAcbResetQueue(CommandBuffer* buf, uint32_t op, uint32_t value) {
(void)value;
Agc::Command::Require(buf != nullptr, __func__, "null command buffer");
constexpr std::uint32_t OpcodeNop = 0x10;
constexpr std::uint32_t CustomDispatchReset = 0x09;
auto* packet = Agc::Command::Allocate(buf, 2, __func__);
packet[0] = Agc::Command::Header(OpcodeNop, 2, CustomDispatchReset << 2);
packet[1] = op;
return packet;
}
std::uint32_t* APS5_VABI sceAgcAcbRewind(CommandBuffer* buf, std::uint32_t initialState) {

View File

@ -10,11 +10,11 @@
extern "C" {
uint32_t* APS5_VABI sceAgcAcbDispatchIndirect(CommandBuffer* buf, const volatile void* indirect_args, uint32_t modifier) {
(void)buf;
(void)indirect_args;
(void)modifier;
NotImplemented_nid_no_patch(__func__);
return nullptr;
// Compute queues take the argument address directly (DISPATCH_INDIRECT with a 64-bit address).
const auto address = reinterpret_cast<std::uintptr_t>(indirect_args);
Agc::Command::CheckAddress(address, 4, __func__);
Agc::Command::CheckBits(modifier, 0xa038u | 0x41u, __func__);
return Agc::Command::Emit(buf, 0x16u, {static_cast<std::uint32_t>(address), static_cast<std::uint32_t>(address >> 32u), modifier | 0x41u}, __func__);
}
std::uint32_t APS5_VABI sceAgcAcbDispatchIndirectGetSize() {

View File

@ -1,4 +1,5 @@
add_library(libSceAgc SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/Unimplemented.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Acb/src/Control.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Acb/src/Dispatch.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Acb/src/Memory.cpp

View File

@ -9,7 +9,7 @@
extern "C" {
std::uint32_t* APS5_VABI sceAgcCbDispatch(CommandBuffer* buf, std::uint32_t threadGroupX, std::uint32_t threadGroupY, std::uint32_t threadGroupZ, std::uint32_t modifier) {
Agc::Command::CheckBits(modifier, 0xa038u, __func__);
Agc::Command::CheckBits(modifier, 0xa038u | 0x41u, __func__);
return Agc::Command::Emit(buf, 0x15u, {threadGroupX, threadGroupY, threadGroupZ, modifier | 0x41u}, __func__);
}

View File

@ -1,6 +1,8 @@
#include "prx/libSceAgc/Cb/include/Sync.hpp"
#include "prx/libSceAgc/Command/include/Packet.hpp"
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
@ -37,10 +39,9 @@ std::uint32_t* APS5_VABI sceAgcCbReleaseMem(CommandBuffer* buf, std::uint8_t act
} else if (dataSelect == 5) {
Agc::Command::Require(data == 0, __func__, "GDS release cannot use immediate data");
value = gdsOffset | (static_cast<std::uint64_t>(gdsSize) << 16u);
} else {
Agc::Command::Require(gdsOffset == 0 && gdsSize == 0, __func__, "GDS parameters supplied for a non-GDS release");
}
if (dataSelect != 0 && interrupt != 4) {
// A null label is accepted: games emit releases whose destination is never read.
if (dataSelect != 0 && interrupt != 4 && guestAddress != 0) {
Agc::Command::CheckAddress(guestAddress, dataSelect == 2 || dataSelect == 3 ? 8 : 4, __func__);
}
if (dataSelect == 1) {
@ -51,7 +52,10 @@ std::uint32_t* APS5_VABI sceAgcCbReleaseMem(CommandBuffer* buf, std::uint8_t act
control |= 0x200u;
}
const auto eventIndex = action >= 0x2fu ? 6u : 5u;
return Agc::Command::Emit(buf, 0x49u, {action | (eventIndex << 8u) | (control << 12u) | (static_cast<std::uint32_t>(cachePolicy) << 25u), (static_cast<std::uint32_t>(dst) << 16u) | (static_cast<std::uint32_t>(interrupt) << 24u) | (static_cast<std::uint32_t>(dataSelect) << 29u), static_cast<std::uint32_t>(guestAddress), static_cast<std::uint32_t>(guestAddress >> 32u), static_cast<std::uint32_t>(value), static_cast<std::uint32_t>(value >> 32u), interruptContextId}, __func__);
auto* packet = Agc::Command::Emit(buf, 0x49u, {action | (eventIndex << 8u) | (control << 12u) | (static_cast<std::uint32_t>(cachePolicy) << 25u), (static_cast<std::uint32_t>(dst) << 16u) | (static_cast<std::uint32_t>(interrupt) << 24u) | (static_cast<std::uint32_t>(dataSelect) << 29u), static_cast<std::uint32_t>(guestAddress), static_cast<std::uint32_t>(guestAddress >> 32u), static_cast<std::uint32_t>(value), static_cast<std::uint32_t>(value >> 32u), interruptContextId}, __func__);
static const std::uint64_t traced = [] { const char* value = std::getenv("APS5_TRACE_LABEL"); return value ? std::strtoull(value, nullptr, 16) : 0ull; }();
if (traced != 0 && guestAddress == traced) std::fprintf(stderr, "[agc] RELEASE_MEM for 0x%llx recorded at %p" "\n", static_cast<unsigned long long>(guestAddress), static_cast<void*>(packet));
return packet;
}
}

View File

@ -53,11 +53,13 @@ std::uint32_t* WriteWait(CommandBuffer* buffer, std::uint8_t size, std::uint8_t
CheckBits(cachePolicy, 3, function);
Require((pollCycles >> 4u) <= 0xffffu, function, "wait poll interval overflow");
if (size == 0) {
CheckBits(reference, 0xffffffffu, function);
CheckBits(mask, 0xffffffffu, function);
// 32-bit waits only use the low halves; guests commonly pass a full 64-bit mask.
reference &= 0xffffffffu;
mask &= 0xffffffffu;
}
const auto guestAddress = reinterpret_cast<std::uintptr_t>(address);
CheckAddress(guestAddress, size == 0 ? 4 : 8, function);
// The address may be left null and filled in later with sceAgcWaitRegMemPatchAddress.
if (guestAddress != 0) CheckAddress(guestAddress, size == 0 ? 4 : 8, function);
CheckBits(guestAddress, 0xffffffffffffull, function);
const auto waitSize = size == 0 ? 7u : 9u;
auto* packet = Allocate(buffer, waitSize + 7u, function);

View File

@ -15,7 +15,10 @@ void Require(bool condition, const char* function, const char* reason) {
}
void CheckBits(std::uint64_t value, std::uint64_t mask, const char* function) {
Require((value & ~mask) == 0, function, "reserved bits are set");
if ((value & ~mask) == 0) return;
char reason[96];
std::snprintf(reason, sizeof(reason), "reserved bits are set (value 0x%llx, allowed 0x%llx)", static_cast<unsigned long long>(value), static_cast<unsigned long long>(mask));
Require(false, function, reason);
}
void CheckAddress(std::uint64_t address, std::uint32_t alignment, const char* function) {

View File

@ -19,15 +19,11 @@ std::uint32_t APS5_VABI sceAgcDcbSetIndexBufferGetSize() {
}
uint32_t* APS5_VABI sceAgcDcbSetIndexCount(CommandBuffer* buf, uint32_t index_count) {
(void)buf;
(void)index_count;
NotImplemented_nid_no_patch(__func__);
return nullptr;
return Agc::Command::Emit(buf, 0x13u, {index_count}, __func__);
}
std::uint32_t APS5_VABI sceAgcDcbSetIndexCountGetSize() {
NotImplemented_nid_no_patch(__func__);
return 0;
return 2;
}
std::uint32_t* APS5_VABI sceAgcDcbSetIndexSize(CommandBuffer* buf, std::uint8_t indexSize, std::uint8_t cachePolicy) {

View File

@ -17,11 +17,17 @@ std::uint32_t APS5_VABI sceAgcDcbSetNumInstancesGetSize() {
}
uint32_t* APS5_VABI sceAgcDcbSetBaseIndirectArgs(CommandBuffer* buf, uint32_t shader_type, const volatile void* indirect_base_addr) {
(void)buf;
(void)shader_type;
(void)indirect_base_addr;
NotImplemented_nid_no_patch(__func__);
return nullptr;
// SET_BASE with base index 1; header bit 1 selects the dispatch (compute) base over the draw base.
Agc::Command::CheckBits(shader_type, 1, __func__);
const auto address = reinterpret_cast<std::uintptr_t>(indirect_base_addr);
Agc::Command::CheckAddress(address, 8, __func__);
Agc::Command::CheckBits(address, 0xffffffffffffull, __func__);
auto* packet = Agc::Command::Allocate(buf, 4, __func__);
packet[0] = Agc::Command::Header(0x11u, 4, shader_type != 0 ? 2u : 0u);
packet[1] = 1;
packet[2] = static_cast<std::uint32_t>(address);
packet[3] = static_cast<std::uint32_t>(address >> 32u);
return packet;
}
}

View File

@ -15,9 +15,10 @@ std::uint32_t* APS5_VABI sceAgcDcbGetLodStats(CommandBuffer* buf, std::uint8_t c
Agc::Command::CheckBits(reportAndReset, 1, __func__);
Agc::Command::CheckBits(reportingIntervalIn100kClocks, 0xffu, __func__);
const auto address = reinterpret_cast<std::uintptr_t>(buffer);
Agc::Command::CheckAddress(address, 64, __func__);
if (address != 0) Agc::Command::CheckAddress(address, 64, __func__);
const auto control = (static_cast<std::uint32_t>(cachePolicy) << 28u) | (static_cast<std::uint32_t>(reportAndReset) << 19u) | (static_cast<std::uint32_t>(forceReset) << 18u) | (resetCount << 10u) | (reportingIntervalIn100kClocks << 2u);
return Agc::Command::Emit(buf, 0x8eu, {bufferSizeInBytes, static_cast<std::uint32_t>(address), static_cast<std::uint32_t>(address >> 32u), control}, __func__);
// LOD statistics are not collected; a same-sized NOP keeps the packet layout without producing data.
return Agc::Command::Emit(buf, 0x10u, {bufferSizeInBytes, static_cast<std::uint32_t>(address), static_cast<std::uint32_t>(address >> 32u), control}, __func__);
}
std::uint32_t APS5_VABI sceAgcDcbBeginOcclusionQueryGetSize() {

View File

@ -51,11 +51,9 @@ uint32_t APS5_VABI sceAgcDcbRewindGetSize(void) {
}
uint32_t* APS5_VABI sceAgcDcbWaitUntilSafeForRendering(CommandBuffer* buf, uint32_t video_out_handle, uint32_t display_buffer_index) {
(void)buf;
(void)video_out_handle;
(void)display_buffer_index;
NotImplemented_nid_no_patch(__func__);
return nullptr;
// Presentation copies the display buffer when the flip executes, so the buffer is always safe to
// render into; keep the arguments in a NOP for command-buffer dumps.
return Agc::Command::Emit(buf, 0x10u, {video_out_handle, display_buffer_index}, __func__);
}
}

View File

@ -10,11 +10,9 @@
extern "C" {
uint32_t* APS5_VABI sceAgcDcbDispatchIndirect(CommandBuffer* buf, uint32_t data_offset_in_bytes, uint32_t flags) {
(void)buf;
(void)data_offset_in_bytes;
(void)flags;
NotImplemented_nid_no_patch(__func__);
return nullptr;
// Graphics queues read the arguments at an offset from the base set by SetBaseDispatchIndirectArgs.
Agc::Command::CheckBits(flags, 0xa038u | 0x41u, __func__);
return Agc::Command::Emit(buf, 0x16u, {data_offset_in_bytes, flags | 0x41u}, __func__);
}
std::uint32_t APS5_VABI sceAgcDcbDispatchIndirectGetSize() {

View File

@ -13,10 +13,13 @@ std::uint32_t* APS5_VABI sceAgcDcbAcquireMem(CommandBuffer* buf, std::uint8_t en
Agc::Command::CheckBits(engine, 1, __func__);
Agc::Command::CheckBits(cbDbOp, 0x7fffffffu, __func__);
Agc::Command::CheckBits(gcrControl, 0x7ffffu, __func__);
const auto address = reinterpret_cast<std::uintptr_t>(base);
Agc::Command::Require((address & 0xffu) == 0 && (address >> 40u) == 0, __func__, "invalid acquire memory base address");
const auto wholeAddressSpace = sizeBytes == 0xffffffffffffffffull;
Agc::Command::Require(wholeAddressSpace || ((sizeBytes & 0xffu) == 0 && (sizeBytes >> 40u) == 0), __func__, "invalid acquire memory range size");
// The range only scopes cache maintenance, so round it outward to the 256-byte granularity the
// packet encodes instead of rejecting unaligned ranges.
const auto requested = reinterpret_cast<std::uintptr_t>(base);
auto address = requested & ~static_cast<std::uintptr_t>(0xffu);
const auto wholeAddressSpace = sizeBytes == 0xffffffffffffffffull || (address >> 40u) != 0 || sizeBytes > (1ull << 40u);
if (wholeAddressSpace) address = 0;
else sizeBytes = (sizeBytes + (requested - address) + 0xffu) & ~0xffull;
Agc::Command::Require(pollCycles / 40u <= 0xffffu, __func__, "acquire poll interval overflow");
return Agc::Command::Emit(buf, 0x58u, {(static_cast<std::uint32_t>(engine) << 31u) | cbDbOp, wholeAddressSpace ? 0u : static_cast<std::uint32_t>(sizeBytes >> 8u), 0, static_cast<std::uint32_t>(address >> 8u), 0, pollCycles / 40u, gcrControl}, __func__);
}

View File

@ -3,31 +3,57 @@
#include "prx/libSceAgc/Command/include/Packet.hpp"
#include <cstdint>
#include <cstddef>
#include <cstring>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
// Debug markers are custom NOP packets: PUSH carries the NUL-terminated text, POP has no payload.
// Marker colors are only meaningful to capture tools and are not encoded.
namespace {
constexpr std::uint32_t OpcodeNop = 0x10;
constexpr std::uint32_t CustomPushMarker = 0x0b;
constexpr std::uint32_t CustomPopMarker = 0x0c;
std::uint32_t* PushMarker(CommandBuffer* buf, const char* str, const char* function) {
Agc::Command::Require(buf != nullptr, function, "null command buffer");
const char* text = str ? str : "";
const std::size_t bytes = std::strlen(text) + 1;
const auto payload = static_cast<std::uint32_t>((bytes + 3) / 4);
Agc::Command::Require(payload <= 0x4000u, function, "marker text too long");
auto* packet = Agc::Command::Allocate(buf, payload + 1, function);
packet[0] = Agc::Command::Header(OpcodeNop, payload + 1, CustomPushMarker << 2);
std::memset(packet + 1, 0, payload * sizeof(std::uint32_t));
std::memcpy(packet + 1, text, bytes);
return packet;
}
std::uint32_t* PopMarker(CommandBuffer* buf, const char* function) {
Agc::Command::Require(buf != nullptr, function, "null command buffer");
auto* packet = Agc::Command::Allocate(buf, 2, function);
packet[0] = Agc::Command::Header(OpcodeNop, 2, CustomPopMarker << 2);
packet[1] = 0;
return packet;
}
}
extern "C" {
uint32_t* APS5_VABI sceAgcDcbSetMarker(CommandBuffer* buf, const char* str, uint32_t color) {
(void)buf;
(void)str;
(void)color;
NotImplemented_nid_no_patch(__func__);
return nullptr;
(void)color;
auto* packet = PushMarker(buf, str, __func__);
PopMarker(buf, __func__);
return packet;
}
uint32_t* APS5_VABI sceAgcDcbPopMarker(CommandBuffer* buf) {
(void)buf;
NotImplemented_nid_no_patch(__func__);
return nullptr;
return PopMarker(buf, __func__);
}
uint32_t* APS5_VABI sceAgcDcbPushMarker(CommandBuffer* buf, const char* str, uint32_t color) {
(void)buf;
(void)str;
(void)color;
NotImplemented_nid_no_patch(__func__);
return nullptr;
(void)color;
return PushMarker(buf, str, __func__);
}
}

View File

@ -30,9 +30,17 @@ int APS5_VABI sceAgcWaitRegMemPatchReference(std::uint32_t* cmd, std::uint64_t r
}
int APS5_VABI sceAgcWaitRegMemPatchCompareFunction(std::uint32_t* cmd, std::uint8_t compareFunction) {
(void)cmd;
(void)compareFunction;
NotImplemented_nid_no_patch(__func__);
auto* wait = Agc::Command::ValidateWait(cmd, __func__);
Agc::Command::Require(compareFunction <= 6, __func__, "invalid wait comparison");
wait[1] = (wait[1] & ~7u) | compareFunction;
return 0;
}
int APS5_VABI sceAgcWriteDataPatchSetAddressOrOffset(std::uint32_t* cmd, std::uint64_t address) {
Agc::Command::CheckAddress(reinterpret_cast<std::uintptr_t>(cmd), 4, __func__);
Agc::Command::Require(((cmd[0] >> 8u) & 0xffu) == 0x37u, __func__, "not a WRITE_DATA packet");
cmd[2] = static_cast<std::uint32_t>(address);
cmd[3] = static_cast<std::uint32_t>(address >> 32u);
return 0;
}

View File

@ -0,0 +1,172 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
int APS5_VABI sceAgcAcbPushMarkerSpan() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcAcbSetMarkerSpan() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcAcbSetWorkloadComplete() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcAcbSetWorkloadStreamInactive() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcAcbSetWorkloadsActive() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcAcquireMemSetEngine() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcDcbPushMarkerSpan() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcDcbSetMarkerSpan() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcDcbSetWorkloadStreamInactive() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcDebugRaiseException() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcGetDataPacketPayloadRange() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcGetDefaultCxStateFlat() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcGetGsOversubscription() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcGetIsTrinityMode() {
return 0;
}
int APS5_VABI sceAgcGetSemaphoreLabel() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAgcSetAmmSemaphoreMemory() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("-KRzWekV120", sceAgcUnknown__MKRzWekV120);
// Unnamed DCB state toggle: games call it as (cb, enable, 0, 0) and ignore the result. It sits
// between SetBaseIndirectArgs and SetIndexBuffer in the import table; treated as a no-op.
std::uint32_t* APS5_VABI sceAgcUnknown__MKRzWekV120(void* buf, std::uint32_t enable, std::uint64_t a2, std::uint64_t a3) {
static bool logged = false;
if (!logged) {
logged = true;
std::fprintf(stderr, "[agc] -KRzWekV120 treated as no-op (enable=%u args=0x%llx,0x%llx)" "\n", enable, static_cast<unsigned long long>(a2), static_cast<unsigned long long>(a3));
}
(void)buf;
return nullptr;
}
APS5_EXPORT("6nths4DHNrs", sceAgcUnknown_6nths4DHNrs);
int APS5_VABI sceAgcUnknown_6nths4DHNrs() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("7Wa3aeJgeVU", sceAgcUnknown_7Wa3aeJgeVU);
int APS5_VABI sceAgcUnknown_7Wa3aeJgeVU() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("EJBA4dbmvfg", sceAgcUnknown_EJBA4dbmvfg);
int APS5_VABI sceAgcUnknown_EJBA4dbmvfg() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("ICkECTBxrMw", sceAgcUnknown_ICkECTBxrMw);
int APS5_VABI sceAgcUnknown_ICkECTBxrMw() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("Ikfdt-rIqCE", sceAgcUnknown_Ikfdt_MrIqCE);
int APS5_VABI sceAgcUnknown_Ikfdt_MrIqCE() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("RTpj-tIlvZc", sceAgcUnknown_RTpj_MtIlvZc);
int APS5_VABI sceAgcUnknown_RTpj_MtIlvZc() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("SwI6QxqwAC0", sceAgcUnknown_SwI6QxqwAC0);
int APS5_VABI sceAgcUnknown_SwI6QxqwAC0() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("d4NZIlguzv0", sceAgcUnknown_d4NZIlguzv0);
int APS5_VABI sceAgcUnknown_d4NZIlguzv0() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("eAy8eGNsCuU", sceAgcUnknown_eAy8eGNsCuU);
int APS5_VABI sceAgcUnknown_eAy8eGNsCuU() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("rP5xLdOf26k", sceAgcUnknown_rP5xLdOf26k);
int APS5_VABI sceAgcUnknown_rP5xLdOf26k() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("tmy-+rBpspY", sceAgcUnknown_tmy_M_PrBpspY);
int APS5_VABI sceAgcUnknown_tmy_M_PrBpspY() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("y5K5tPktiL8", sceAgcUnknown_y5K5tPktiL8);
int APS5_VABI sceAgcUnknown_y5K5tPktiL8() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
}

View File

@ -94,7 +94,7 @@ int APS5_VABI sceAjmModuleUnregister(uint32_t context, uint32_t codec) {
return 0;
}
const char* sceAjmStrError(int error) {
const char* APS5_VABI sceAjmStrError(int error) {
(void)error;
NotImplemented_nid_no_patch(__func__);
return nullptr;

View File

@ -94,7 +94,7 @@ int APS5_VABI sceAjmModuleUnregister(uint32_t context, uint32_t codec) {
return 0;
}
const char* sceAjmStrError(int error) {
const char* APS5_VABI sceAjmStrError(int error) {
(void)error;
NotImplemented_nid_no_patch(__func__);
return nullptr;

View File

@ -0,0 +1,335 @@
#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 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;
}
extern "C" {
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() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAmprCommandBufferPushMarker() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAmprCommandBufferPushMarkerWithColor() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
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() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAmprCommandBufferSetMarkerWithColor() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
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;
}
int APS5_VABI sceAmprMeasureCommandSizePopMarker() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAmprMeasureCommandSizePushMarker() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAmprMeasureCommandSizePushMarkerWithColor() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
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;
}
int APS5_VABI sceAmprMeasureCommandSizeSetMarker() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceAmprMeasureCommandSizeSetMarkerWithColor() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
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;
}
}

View File

@ -2,6 +2,11 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <cstring>
static constexpr int SCE_APP_CONTENT_ERROR_PARAMETER = static_cast<int>(0x80D90002);
static constexpr uint32_t APPPARAM_ID_SKU_FLAG = 1;
static constexpr int32_t SKU_FLAG_FULL = 3;
extern "C" {
@ -20,10 +25,17 @@ int APS5_VABI sceAppContentAddcontUnmount(const AppContentMountPoint* mount_poin
}
int APS5_VABI sceAppContentAppParamGetInt(uint32_t param_id, int32_t* value) {
(void)param_id;
(void)value;
NotImplemented_nid_no_patch(__func__);
return 0;
if (!value) return SCE_APP_CONTENT_ERROR_PARAMETER;
switch (param_id) {
case APPPARAM_ID_SKU_FLAG:
*value = SKU_FLAG_FULL;
return 0;
case 2: case 3: case 4: case 5:
*value = 0;
return 0;
default:
return SCE_APP_CONTENT_ERROR_PARAMETER;
}
}
int APS5_VABI sceAppContentDownloadDataGetAvailableSpaceKb(const AppContentMountPoint* mount_point, size_t* available_space_kb) {
@ -34,10 +46,10 @@ int APS5_VABI sceAppContentDownloadDataGetAvailableSpaceKb(const AppContentMount
}
int APS5_VABI sceAppContentInitialize(const AppContentInitParam* init_param, AppContentBootParam* boot_param) {
(void)init_param;
(void)boot_param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)init_param;
if (!boot_param) return SCE_APP_CONTENT_ERROR_PARAMETER;
std::memset(boot_param, 0, sizeof(*boot_param));
return 0;
}
int APS5_VABI sceAppContentTemporaryDataFormat(const AppContentMountPoint* mount_point) {

View File

@ -5,7 +5,7 @@
extern "C" {
const uint8_t* sceCesRefersUcsProfileCp1252(void) {
const uint8_t* APS5_VABI sceCesRefersUcsProfileCp1252(void) {
NotImplemented_nid_no_patch(__func__);
return nullptr;
}

View File

@ -2,79 +2,398 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <thread>
#include <stdexcept>
#include <string>
#include <xmmintrin.h>
#ifdef _WIN32
#include <windows.h>
#endif
static constexpr int32_t SCE_OK = 0;
static constexpr int32_t SCE_FIBER_ERROR_NULL = static_cast<int32_t>(0x80590001);
static constexpr int32_t SCE_FIBER_ERROR_ALIGNMENT = static_cast<int32_t>(0x80590002);
static constexpr int32_t SCE_FIBER_ERROR_RANGE = static_cast<int32_t>(0x80590003);
static constexpr int32_t SCE_FIBER_ERROR_INVALID = static_cast<int32_t>(0x80590004);
static constexpr int32_t SCE_FIBER_ERROR_PERMISSION = static_cast<int32_t>(0x80590005);
static constexpr int32_t SCE_FIBER_ERROR_STATE = static_cast<int32_t>(0x80590006);
static constexpr std::size_t FIBER_OBJECT_SIZE = 0x100;
static constexpr std::size_t FIBER_OPT_PARAM_SIZE = 0x80;
static constexpr std::size_t FIBER_MIN_CONTEXT_SIZE = 512;
#ifdef _WIN32
using GuestFiberEntry = void (APS5_VABI*)(std::uint64_t argOnInitialize, std::uint64_t argOnRun);
// A fiber that is switching away stays Suspending until its context is saved; whoever runs next
// on that host thread publishes Suspended. Fibers migrate between threads, so a resumer must never
// see Suspended before the saved stack pointer is valid.
enum class FiberState : std::uint32_t {
Idle = 1,
Running = 2,
Suspending = 3,
Suspended = 4,
};
struct Fiber {
std::uint64_t magic;
std::atomic<FiberState> state;
std::uint32_t reserved;
GuestFiberEntry entry;
std::uint64_t argOnInitialize;
std::uint8_t* context;
std::uint64_t contextSize;
void* savedStack;
char name[FIBER_MAX_NAME_LENGTH + 1];
};
static_assert(sizeof(Fiber) <= FIBER_OBJECT_SIZE, "guest reserves 0x100 bytes for SceFiber");
static constexpr std::uint64_t FIBER_MAGIC = 0x5245424946355041ull;
struct StackBounds {
void* base;
void* limit;
void* deallocation;
};
struct ThreadFiberState {
Fiber* current = nullptr;
void* threadStack = nullptr;
StackBounds threadBounds{};
std::uint64_t transfer = 0;
Fiber* pendingSuspend = nullptr;
};
static thread_local ThreadFiberState g_thread;
// A fiber may resume on a different host thread than the one that suspended it, so the
// thread-local state must be looked up again after every stack switch rather than cached.
__attribute__((noinline)) static ThreadFiberState& ThreadState() {
asm volatile("" ::: "memory");
return g_thread;
}
static bool TraceFibers() {
static const bool enabled = std::getenv("APS5_TRACE_FIBER") != nullptr;
return enabled;
}
static void CompletePendingSuspend() {
auto& thread = ThreadState();
if (thread.pendingSuspend) {
thread.pendingSuspend->state.store(FiberState::Suspended, std::memory_order_release);
thread.pendingSuspend = nullptr;
}
}
extern "C" void Aps5FiberSwitchStack(void** save, void* load);
extern "C" void Aps5FiberTrampoline();
asm(R"(
.text
.globl Aps5FiberSwitchStack
.def Aps5FiberSwitchStack; .scl 2; .type 32; .endef
Aps5FiberSwitchStack:
push %rbp
push %rbx
push %rdi
push %rsi
push %r12
push %r13
push %r14
push %r15
sub $0xa8, %rsp
movaps %xmm6, 0x00(%rsp)
movaps %xmm7, 0x10(%rsp)
movaps %xmm8, 0x20(%rsp)
movaps %xmm9, 0x30(%rsp)
movaps %xmm10, 0x40(%rsp)
movaps %xmm11, 0x50(%rsp)
movaps %xmm12, 0x60(%rsp)
movaps %xmm13, 0x70(%rsp)
movaps %xmm14, 0x80(%rsp)
movaps %xmm15, 0x90(%rsp)
stmxcsr 0xa0(%rsp)
fnstcw 0xa4(%rsp)
mov %rsp, (%rcx)
mov %rdx, %rsp
movaps 0x00(%rsp), %xmm6
movaps 0x10(%rsp), %xmm7
movaps 0x20(%rsp), %xmm8
movaps 0x30(%rsp), %xmm9
movaps 0x40(%rsp), %xmm10
movaps 0x50(%rsp), %xmm11
movaps 0x60(%rsp), %xmm12
movaps 0x70(%rsp), %xmm13
movaps 0x80(%rsp), %xmm14
movaps 0x90(%rsp), %xmm15
ldmxcsr 0xa0(%rsp)
fldcw 0xa4(%rsp)
add $0xa8, %rsp
pop %r15
pop %r14
pop %r13
pop %r12
pop %rsi
pop %rdi
pop %rbx
pop %rbp
ret
.globl Aps5FiberTrampoline
.def Aps5FiberTrampoline; .scl 2; .type 32; .endef
Aps5FiberTrampoline:
mov %r12, %rcx
and $-16, %rsp
sub $32, %rsp
call Aps5FiberMain
ud2
)");
struct InitialFrame {
std::uint8_t xmm[0xa0];
std::uint32_t mxcsr;
std::uint16_t fpuControl;
std::uint16_t padding;
std::uint64_t r15, r14, r13, r12, rsi, rdi, rbx, rbp;
std::uint64_t returnAddress;
};
static_assert(sizeof(InitialFrame) == 0xa8 + 8 * 8 + 8, "initial fiber frame must match Aps5FiberSwitchStack");
static StackBounds CurrentBounds() {
auto* tib = reinterpret_cast<NT_TIB*>(NtCurrentTeb());
auto* teb = reinterpret_cast<std::uint8_t*>(tib);
return {tib->StackBase, tib->StackLimit, *reinterpret_cast<void**>(teb + 0x1478)};
}
static void SetBounds(const StackBounds& bounds) {
auto* tib = reinterpret_cast<NT_TIB*>(NtCurrentTeb());
auto* teb = reinterpret_cast<std::uint8_t*>(tib);
tib->StackBase = bounds.base;
tib->StackLimit = bounds.limit;
*reinterpret_cast<void**>(teb + 0x1478) = bounds.deallocation;
}
static StackBounds FiberBounds(const Fiber* fiber) {
return {fiber->context + fiber->contextSize, fiber->context, fiber->context};
}
static Fiber* AsFiber(FiberObject* object) {
auto* fiber = reinterpret_cast<Fiber*>(object);
return fiber && fiber->magic == FIBER_MAGIC ? fiber : nullptr;
}
extern "C" [[noreturn]] void Aps5FiberMain(Fiber* fiber) {
CompletePendingSuspend();
fiber->entry(fiber->argOnInitialize, ThreadState().transfer);
throw std::runtime_error(std::string("sceFiber: entry function of fiber '") + fiber->name + "' returned");
}
static void PrepareInitialStack(Fiber* fiber) {
const auto top = reinterpret_cast<std::uintptr_t>(fiber->context + fiber->contextSize) & ~static_cast<std::uintptr_t>(15);
auto* frame = reinterpret_cast<InitialFrame*>(top - 256);
std::memset(frame, 0, sizeof(*frame));
frame->mxcsr = _mm_getcsr();
std::uint16_t control = 0;
asm volatile("fnstcw %0" : "=m"(control));
frame->fpuControl = control;
frame->r12 = reinterpret_cast<std::uint64_t>(fiber);
frame->returnAddress = reinterpret_cast<std::uint64_t>(&Aps5FiberTrampoline);
fiber->savedStack = frame;
}
static bool AcquireForResume(Fiber* target) {
for (;;) {
auto state = target->state.load(std::memory_order_acquire);
if (state == FiberState::Suspending) {
std::this_thread::yield();
continue;
}
if (state != FiberState::Idle && state != FiberState::Suspended) return false;
if (target->state.compare_exchange_weak(state, FiberState::Running, std::memory_order_acq_rel)) {
if (state == FiberState::Idle) PrepareInitialStack(target);
return true;
}
}
}
static void Resume(Fiber* target, void** save, std::uint64_t argOnRun) {
const auto* frame = static_cast<const InitialFrame*>(target->savedStack);
if (frame->returnAddress == 0) {
std::fprintf(stderr, "[fiber] resuming '%s' with a wiped context: saved=%p context=%p size=0x%llx\n", target->name, target->savedStack,
static_cast<void*>(target->context), static_cast<unsigned long long>(target->contextSize));
const auto* words = static_cast<const std::uint64_t*>(target->savedStack);
for (int i = 0; i < 40; i += 4) std::fprintf(stderr, "[fiber] +0x%03x %016llx %016llx %016llx %016llx\n", i * 8, static_cast<unsigned long long>(words[i]), static_cast<unsigned long long>(words[i + 1]), static_cast<unsigned long long>(words[i + 2]), static_cast<unsigned long long>(words[i + 3]));
std::fflush(stderr);
std::abort();
}
ThreadState().current = target;
ThreadState().transfer = argOnRun;
SetBounds(FiberBounds(target));
Aps5FiberSwitchStack(save, target->savedStack);
}
extern "C" {
int32_t APS5_VABI sceFiberFinalize(FiberObject* fiber) {
(void)fiber;
NotImplemented_nid_no_patch(__func__);
return 0;
int32_t APS5_VABI _sceFiberInitializeImpl_nid_postfix(FiberObject* object, const char* name, GuestFiberEntry entry, uint64_t arg_on_initialize, void* addr_context, uint64_t size_context, const void* opt_param, uint32_t build_version) {
(void)opt_param;
(void)build_version;
if (!object || !name || !entry) return SCE_FIBER_ERROR_NULL;
if ((reinterpret_cast<std::uintptr_t>(object) & 7) != 0) return SCE_FIBER_ERROR_ALIGNMENT;
if (addr_context == nullptr && size_context != 0) return SCE_FIBER_ERROR_INVALID;
if ((reinterpret_cast<std::uintptr_t>(addr_context) & 15) != 0 || (size_context & 15) != 0) return SCE_FIBER_ERROR_ALIGNMENT;
if (addr_context == nullptr) return SCE_FIBER_ERROR_INVALID;
if (size_context < FIBER_MIN_CONTEXT_SIZE) return SCE_FIBER_ERROR_RANGE;
auto* fiber = reinterpret_cast<Fiber*>(object);
std::memset(object, 0, FIBER_OBJECT_SIZE);
fiber->magic = FIBER_MAGIC;
fiber->state.store(FiberState::Idle, std::memory_order_relaxed);
fiber->entry = entry;
fiber->argOnInitialize = arg_on_initialize;
fiber->context = static_cast<std::uint8_t*>(addr_context);
fiber->contextSize = size_context;
std::strncpy(fiber->name, name, FIBER_MAX_NAME_LENGTH);
if (TraceFibers()) std::fprintf(stderr, "[fiber] init %s object=%p context=%p+0x%llx entry=%p\n", fiber->name, static_cast<void*>(object), addr_context, static_cast<unsigned long long>(size_context), reinterpret_cast<void*>(entry));
return SCE_OK;
}
int32_t APS5_VABI sceFiberGetInfo(FiberObject* fiber, FiberInfo* fiber_info) {
(void)fiber;
(void)fiber_info;
NotImplemented_nid_no_patch(__func__);
return 0;
int32_t APS5_VABI sceFiberFinalize(FiberObject* object) {
auto* fiber = AsFiber(object);
if (!fiber) return object ? SCE_FIBER_ERROR_INVALID : SCE_FIBER_ERROR_NULL;
const auto state = fiber->state.load(std::memory_order_acquire);
if (state == FiberState::Running || state == FiberState::Suspending) return SCE_FIBER_ERROR_STATE;
fiber->magic = 0;
return SCE_OK;
}
int32_t APS5_VABI sceFiberGetSelf(FiberObject** fiber) {
(void)fiber;
NotImplemented_nid_no_patch(__func__);
return 0;
int32_t APS5_VABI sceFiberRun_nid_postfix(FiberObject* object, uint64_t arg_on_run, uint64_t* arg_on_return) {
auto* fiber = AsFiber(object);
if (!fiber) return object ? SCE_FIBER_ERROR_INVALID : SCE_FIBER_ERROR_NULL;
if (ThreadState().current) return SCE_FIBER_ERROR_PERMISSION;
if (!AcquireForResume(fiber)) return SCE_FIBER_ERROR_STATE;
ThreadState().threadBounds = CurrentBounds();
Resume(fiber, &ThreadState().threadStack, arg_on_run);
CompletePendingSuspend();
SetBounds(ThreadState().threadBounds);
if (arg_on_return) *arg_on_return = ThreadState().transfer;
return SCE_OK;
}
int32_t APS5_VABI sceFiberGetThreadFramePointerAddress(uint64_t* addr_frame_pointer) {
(void)addr_frame_pointer;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int32_t APS5_VABI sceFiberOptParamInitialize(FiberOptParam* opt_param) {
(void)opt_param;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int32_t APS5_VABI sceFiberRename(FiberObject* fiber, const char* name) {
(void)fiber;
(void)name;
NotImplemented_nid_no_patch(__func__);
return 0;
int32_t APS5_VABI sceFiberSwitch(FiberObject* object, uint64_t arg_on_run, uint64_t* arg_on_run_out) {
auto* target = AsFiber(object);
if (!target) return object ? SCE_FIBER_ERROR_INVALID : SCE_FIBER_ERROR_NULL;
auto* self = ThreadState().current;
if (!self) return SCE_FIBER_ERROR_PERMISSION;
if (target == self || !AcquireForResume(target)) return SCE_FIBER_ERROR_STATE;
if (TraceFibers()) {
auto** frame = static_cast<void**>(__builtin_frame_address(0));
void* chain[6] = {};
auto** guest = static_cast<void**>(frame[0]);
for (int depth = 0; depth < 6 && guest; ++depth) {
chain[depth] = guest[1];
guest = static_cast<void**>(guest[0]);
}
std::fprintf(stderr, "[fiber] switch %s -> %s from %p %p %p %p %p %p\n", self->name, target->name, chain[0], chain[1], chain[2], chain[3], chain[4], chain[5]);
}
self->state.store(FiberState::Suspending, std::memory_order_relaxed);
ThreadState().pendingSuspend = self;
Resume(target, &self->savedStack, arg_on_run);
CompletePendingSuspend();
if (arg_on_run_out) *arg_on_run_out = ThreadState().transfer;
return SCE_OK;
}
int32_t APS5_VABI sceFiberReturnToThread(uint64_t arg_on_return, uint64_t* arg_on_run) {
(void)arg_on_return;
(void)arg_on_run;
NotImplemented_nid_no_patch(__func__);
return 0;
auto* self = ThreadState().current;
if (!self) return SCE_FIBER_ERROR_PERMISSION;
if (TraceFibers()) std::fprintf(stderr, "[fiber] return %s from %p\n", self->name, __builtin_return_address(0));
self->state.store(FiberState::Suspending, std::memory_order_relaxed);
ThreadState().pendingSuspend = self;
ThreadState().current = nullptr;
ThreadState().transfer = arg_on_return;
SetBounds(ThreadState().threadBounds);
Aps5FiberSwitchStack(&self->savedStack, ThreadState().threadStack);
CompletePendingSuspend();
if (arg_on_run) *arg_on_run = ThreadState().transfer;
return SCE_OK;
}
int32_t APS5_VABI sceFiberRun_nid_postfix(FiberObject* fiber, uint64_t arg_on_run, uint64_t* arg_on_return) {
(void)fiber;
(void)arg_on_run;
(void)arg_on_return;
NotImplemented_nid_no_patch(__func__);
return 0;
int32_t APS5_VABI sceFiberGetSelf(FiberObject** fiber) {
if (!fiber) return SCE_FIBER_ERROR_NULL;
if (!ThreadState().current) return SCE_FIBER_ERROR_PERMISSION;
*fiber = reinterpret_cast<FiberObject*>(ThreadState().current);
return SCE_OK;
}
int32_t APS5_VABI sceFiberGetInfo(FiberObject* object, FiberInfo* fiber_info) {
auto* fiber = AsFiber(object);
if (!fiber || !fiber_info) return object && fiber_info ? SCE_FIBER_ERROR_INVALID : SCE_FIBER_ERROR_NULL;
if (fiber_info->size != sizeof(FiberInfo)) return SCE_FIBER_ERROR_INVALID;
fiber_info->entry = reinterpret_cast<FiberEntry>(fiber->entry);
fiber_info->arg_on_initialize = fiber->argOnInitialize;
fiber_info->addr_context = fiber->context;
fiber_info->size_context = fiber->contextSize;
std::memcpy(fiber_info->name, fiber->name, sizeof(fiber_info->name));
fiber_info->size_context_margin = static_cast<uint64_t>(-1);
return SCE_OK;
}
int32_t APS5_VABI sceFiberRename(FiberObject* object, const char* name) {
auto* fiber = AsFiber(object);
if (!fiber || !name) return object && name ? SCE_FIBER_ERROR_INVALID : SCE_FIBER_ERROR_NULL;
std::memset(fiber->name, 0, sizeof(fiber->name));
std::strncpy(fiber->name, name, FIBER_MAX_NAME_LENGTH);
return SCE_OK;
}
int32_t APS5_VABI sceFiberOptParamInitialize(FiberOptParam* opt_param) {
if (!opt_param) return SCE_FIBER_ERROR_NULL;
std::memset(opt_param, 0, FIBER_OPT_PARAM_SIZE);
return SCE_OK;
}
int32_t APS5_VABI sceFiberGetThreadFramePointerAddress(uint64_t* addr_frame_pointer) {
(void)addr_frame_pointer;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int32_t APS5_VABI sceFiberStartContextSizeCheck(uint32_t flags) {
(void)flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)flags;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int32_t APS5_VABI sceFiberStopContextSizeCheck(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int32_t APS5_VABI sceFiberSwitch(FiberObject* fiber, uint64_t arg_on_run, uint64_t* arg_on_return) {
(void)fiber;
(void)arg_on_run;
(void)arg_on_return;
NotImplemented_nid_no_patch(__func__);
return 0;
NotImplemented_nid_no_patch(__func__);
return 0;
}
}
#else
extern "C" {
int32_t APS5_VABI _sceFiberInitializeImpl_nid_postfix() { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberFinalize(FiberObject*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberRun_nid_postfix(FiberObject*, uint64_t, uint64_t*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberSwitch(FiberObject*, uint64_t, uint64_t*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberReturnToThread(uint64_t, uint64_t*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberGetSelf(FiberObject**) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberGetInfo(FiberObject*, FiberInfo*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberRename(FiberObject*, const char*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberOptParamInitialize(FiberOptParam*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberGetThreadFramePointerAddress(uint64_t*) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberStartContextSizeCheck(uint32_t) { NotImplemented_nid_no_patch(__func__); return 0; }
int32_t APS5_VABI sceFiberStopContextSizeCheck(void) { NotImplemented_nid_no_patch(__func__); return 0; }
}
#endif

View File

@ -497,7 +497,7 @@ int APS5_VABI sceFontWritingLineWritesOrder(FontWritingLine writing_line, uint64
return 0;
}
const FontWritingStep* sceFontWritingRefersRenderStep(FontWriting* font_writing) {
const FontWritingStep* APS5_VABI sceFontWritingRefersRenderStep(FontWriting* font_writing) {
(void)font_writing;
NotImplemented_nid_no_patch(__func__);
return nullptr;

View File

@ -497,7 +497,7 @@ int APS5_VABI sceFontWritingLineWritesOrder(FontWritingLine writing_line, uint64
return 0;
}
const FontWritingStep* sceFontWritingRefersRenderStep(FontWriting* font_writing) {
const FontWritingStep* APS5_VABI sceFontWritingRefersRenderStep(FontWriting* font_writing) {
(void)font_writing;
NotImplemented_nid_no_patch(__func__);
return nullptr;

View File

@ -3,31 +3,30 @@
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
// Update checks need the network, which is not available; requests fail so the game skips the check.
static constexpr int SCE_GAME_UPDATE_ERROR_OFFLINE = static_cast<int>(0x80D50001);
extern "C" {
int APS5_VABI sceGameUpdateAbortRequest(int request_id) {
(void)request_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
return 0;
}
int APS5_VABI sceGameUpdateCheck(int request_id, const GameUpdateCheckParam* param, GameUpdateCheckResult* result) {
(void)request_id;
(void)param;
(void)result;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)param;
(void)result;
return SCE_GAME_UPDATE_ERROR_OFFLINE;
}
int APS5_VABI sceGameUpdateCreateRequest(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return SCE_GAME_UPDATE_ERROR_OFFLINE;
}
int APS5_VABI sceGameUpdateDeleteRequest(int request_id) {
(void)request_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
return 0;
}
int APS5_VABI sceGameUpdateGetAddcontLatestVersion(uint32_t service_label, const void* entitlement_label, GameUpdateAddcontVersionInfo* info) {
@ -39,13 +38,11 @@ int APS5_VABI sceGameUpdateGetAddcontLatestVersion(uint32_t service_label, const
}
int APS5_VABI sceGameUpdateInitialize(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
int APS5_VABI sceGameUpdateTerminate(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
}

View File

@ -2,40 +2,42 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
// No network is emulated: contexts, templates and requests can be created, but any request
// that would touch the network fails with the library's network error.
static constexpr int ERROR_NETWORK = static_cast<int>(0x80431063);
static std::atomic<int> g_nextHandle{1};
extern "C" {
int APS5_VABI sceHttpAbortRequest(int request_id) {
(void)request_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
return 0;
}
int APS5_VABI sceHttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode) {
(void)id;
(void)name;
(void)value;
(void)mode;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)name;
(void)value;
(void)mode;
return 0;
}
int APS5_VABI sceHttpCreateConnection(int tmpl_id, const char* server_name, const char* scheme, uint16_t port, int enable_keep_alive) {
(void)tmpl_id;
(void)server_name;
(void)scheme;
(void)port;
(void)enable_keep_alive;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)tmpl_id;
(void)server_name;
(void)scheme;
(void)port;
(void)enable_keep_alive;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttpCreateConnectionWithURL(int tmpl_id, const char* url, int enable_keep_alive) {
(void)tmpl_id;
(void)url;
(void)enable_keep_alive;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)tmpl_id;
(void)url;
(void)enable_keep_alive;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttpCreateEpoll(int http_ctx_id, HttpEpollHandle* eh) {
@ -46,199 +48,172 @@ int APS5_VABI sceHttpCreateEpoll(int http_ctx_id, HttpEpollHandle* eh) {
}
int APS5_VABI sceHttpCreateRequest(int conn_id, int method, const char* path, uint64_t content_length) {
(void)conn_id;
(void)method;
(void)path;
(void)content_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)conn_id;
(void)method;
(void)path;
(void)content_length;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttpCreateRequestWithURL2(int conn_id, const char* method, const char* url, uint64_t content_length) {
(void)conn_id;
(void)method;
(void)url;
(void)content_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)conn_id;
(void)method;
(void)url;
(void)content_length;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver, int is_auto_proxy_conf) {
(void)http_ctx_id;
(void)user_agent;
(void)http_ver;
(void)is_auto_proxy_conf;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)http_ctx_id;
(void)user_agent;
(void)http_ver;
(void)is_auto_proxy_conf;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttpDeleteConnection(int conn_id) {
(void)conn_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)conn_id;
return 0;
}
int APS5_VABI sceHttpDeleteRequest(int req_id) {
(void)req_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
return 0;
}
int APS5_VABI sceHttpDeleteTemplate(int tmpl_id) {
(void)tmpl_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)tmpl_id;
return 0;
}
int APS5_VABI sceHttpDestroyEpoll(int http_ctx_id, HttpEpollHandle eh) {
(void)http_ctx_id;
(void)eh;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)http_ctx_id;
(void)eh;
return 0;
}
int APS5_VABI sceHttpGetAllResponseHeaders(int request_id, char** header, size_t* header_size) {
(void)request_id;
(void)header;
(void)header_size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)header;
(void)header_size;
return ERROR_NETWORK;
}
int APS5_VABI sceHttpGetResponseContentLength(int request_id, int* result, uint64_t* content_length) {
(void)request_id;
(void)result;
(void)content_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)result;
(void)content_length;
return ERROR_NETWORK;
}
int APS5_VABI sceHttpGetStatusCode(int request_id, int* status_code) {
(void)request_id;
(void)status_code;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)status_code;
return ERROR_NETWORK;
}
int APS5_VABI sceHttpInit_nid_postfix(int memid, int ssl_ctx_id, uint64_t pool_size) {
(void)memid;
(void)ssl_ctx_id;
(void)pool_size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)memid;
(void)ssl_ctx_id;
(void)pool_size;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttpsDisableOption(int id, uint32_t ssl_flags) {
(void)id;
(void)ssl_flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)ssl_flags;
return 0;
}
int APS5_VABI sceHttpSendRequest(int request_id, const void* post_data, size_t size) {
(void)request_id;
(void)post_data;
(void)size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)post_data;
(void)size;
return ERROR_NETWORK;
}
int APS5_VABI sceHttpSetAuthEnabled(int id, int enable) {
(void)id;
(void)enable;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)enable;
return 0;
}
int APS5_VABI sceHttpSetAutoRedirect(int id, int enable) {
(void)id;
(void)enable;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)enable;
return 0;
}
int APS5_VABI sceHttpSetConnectTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttpSetEpoll(int id, HttpEpollHandle eh, void* user_arg) {
(void)id;
(void)eh;
(void)user_arg;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)eh;
(void)user_arg;
return 0;
}
int APS5_VABI sceHttpSetNonblock(int id, int enable) {
(void)id;
(void)enable;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)enable;
return 0;
}
int APS5_VABI sceHttpSetRecvTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttpSetRequestContentLength(int request_id, uint64_t content_length) {
(void)request_id;
(void)content_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)content_length;
return 0;
}
int APS5_VABI sceHttpSetResolveRetry(int id, int32_t retry) {
(void)id;
(void)retry;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)retry;
return 0;
}
int APS5_VABI sceHttpSetResolveTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttpSetSendTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttpsSetMinSslVersion(int id, uint32_t ssl_version) {
(void)id;
(void)ssl_version;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)ssl_version;
return 0;
}
int APS5_VABI sceHttpsSetSslCallback(int id, HttpsCallback cbfunc, void* user_arg) {
(void)id;
(void)cbfunc;
(void)user_arg;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)cbfunc;
(void)user_arg;
return 0;
}
int APS5_VABI sceHttpTerm_nid_postfix(int http_ctx_id) {
(void)http_ctx_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)http_ctx_id;
return 0;
}
int APS5_VABI sceHttpUnsetEpoll(int id) {
(void)id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
return 0;
}
int APS5_VABI sceHttpUriBuild(char* out, size_t* require, size_t prepare, const SceHttpUriElement* src_element, uint32_t option) {
@ -271,10 +246,24 @@ int APS5_VABI sceHttpUriParse(SceHttpUriElement* out, const char* src_url, void*
}
int APS5_VABI sceHttpWaitRequest(HttpEpollHandle eh, HttpNBEvent* nbev, int maxevents, int timeout) {
(void)eh;
(void)nbev;
(void)maxevents;
(void)timeout;
(void)eh;
(void)nbev;
(void)maxevents;
(void)timeout;
return ERROR_NETWORK;
}
int APS5_VABI sceHttpCreateRequestWithURL() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceHttpReadData() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceHttpSetChunkedTransferEnabled() {
NotImplemented_nid_no_patch(__func__);
return 0;
}

View File

@ -2,228 +2,209 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
// No network is emulated: contexts, templates and requests can be created, but any request
// that would touch the network fails with the library's network error.
static constexpr int ERROR_NETWORK = static_cast<int>(0x80436063);
static std::atomic<int> g_nextHandle{1};
extern "C" {
int APS5_VABI sceHttp2AddRequestHeader(int id, const char* name, const char* value, uint32_t mode) {
(void)id;
(void)name;
(void)value;
(void)mode;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)name;
(void)value;
(void)mode;
return 0;
}
int APS5_VABI sceHttp2CreateRequestWithURL(int tmpl_id, const char* method, const char* url, uint64_t content_length) {
(void)tmpl_id;
(void)method;
(void)url;
(void)content_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)tmpl_id;
(void)method;
(void)url;
(void)content_length;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttp2CreateTemplate(int lib_http2_ctx_id, const char* user_agent, int http_ver, int is_auto_proxy_conf) {
(void)lib_http2_ctx_id;
(void)user_agent;
(void)http_ver;
(void)is_auto_proxy_conf;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_http2_ctx_id;
(void)user_agent;
(void)http_ver;
(void)is_auto_proxy_conf;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttp2DeleteRequest(int req_id) {
(void)req_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
return 0;
}
int APS5_VABI sceHttp2DeleteTemplate(int tmpl_id) {
(void)tmpl_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)tmpl_id;
return 0;
}
int APS5_VABI sceHttp2GetAllResponseHeaders(int req_id, char** header, size_t* header_size) {
(void)req_id;
(void)header;
(void)header_size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)header;
(void)header_size;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2GetResponseContentLength(int req_id, int* result, uint64_t* content_length) {
(void)req_id;
(void)result;
(void)content_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)result;
(void)content_length;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2GetStatusCode(int req_id, int* status_code) {
(void)req_id;
(void)status_code;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)status_code;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2Init(int libnet_mem_id, int libssl_ctx_id, size_t pool_size, int max_concurrent_request) {
(void)libnet_mem_id;
(void)libssl_ctx_id;
(void)pool_size;
(void)max_concurrent_request;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)libnet_mem_id;
(void)libssl_ctx_id;
(void)pool_size;
(void)max_concurrent_request;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceHttp2ReadData(int req_id, void* data, size_t size) {
(void)req_id;
(void)data;
(void)size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)data;
(void)size;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2ReadDataAsync(int req_id, void* data, size_t size, void* kqueue_option, void* option) {
(void)req_id;
(void)data;
(void)size;
(void)kqueue_option;
(void)option;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)data;
(void)size;
(void)kqueue_option;
(void)option;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2SendRequest(int req_id, const void* post_data, size_t size) {
(void)req_id;
(void)post_data;
(void)size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)post_data;
(void)size;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2SendRequestAsync(int req_id, const void* post_data, size_t size, void* kqueue_option, void* option) {
(void)req_id;
(void)post_data;
(void)size;
(void)kqueue_option;
(void)option;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)post_data;
(void)size;
(void)kqueue_option;
(void)option;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2SetAuthEnabled(int id, int is_enable) {
(void)id;
(void)is_enable;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)is_enable;
return 0;
}
int APS5_VABI sceHttp2SetAutoRedirect(int id, int enable) {
(void)id;
(void)enable;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)enable;
return 0;
}
int APS5_VABI sceHttp2SetConnectionWaitTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttp2SetConnectTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttp2SetInflateGZIPEnabled(int id, int enable) {
(void)id;
(void)enable;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)enable;
return 0;
}
int APS5_VABI sceHttp2SetRecvTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttp2SetRedirectCallback(int id, void* cb_func, void* user_arg) {
(void)id;
(void)cb_func;
(void)user_arg;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)cb_func;
(void)user_arg;
return 0;
}
int APS5_VABI sceHttp2SetRequestContentLength(int id, uint64_t content_length) {
(void)id;
(void)content_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)content_length;
return 0;
}
int APS5_VABI sceHttp2SetResolveTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttp2SetSendTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttp2SetSslCallback(int id, void* cb_func, void* user_arg) {
(void)id;
(void)cb_func;
(void)user_arg;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)cb_func;
(void)user_arg;
return 0;
}
int APS5_VABI sceHttp2SetTimeOut(int id, uint32_t usec) {
(void)id;
(void)usec;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)usec;
return 0;
}
int APS5_VABI sceHttp2SslDisableOption(int id, uint32_t ssl_flags) {
(void)id;
(void)ssl_flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)ssl_flags;
return 0;
}
int APS5_VABI sceHttp2SslEnableOption(int id, uint32_t ssl_flags) {
(void)id;
(void)ssl_flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)id;
(void)ssl_flags;
return 0;
}
int APS5_VABI sceHttp2Term(int lib_http2_ctx_id) {
(void)lib_http2_ctx_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_http2_ctx_id;
return 0;
}
int APS5_VABI sceHttp2WaitAsync(int req_id, Http2AsyncResult* result, uint32_t* timeout, void* option) {
(void)req_id;
(void)result;
(void)timeout;
(void)option;
(void)req_id;
(void)result;
(void)timeout;
(void)option;
return ERROR_NETWORK;
}
int APS5_VABI sceHttp2AbortRequest() {
NotImplemented_nid_no_patch(__func__);
return 0;
}

View File

@ -0,0 +1,28 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
int APS5_VABI sceJpegEncCreate() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceJpegEncDelete() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceJpegEncEncode() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceJpegEncQueryMemorySize() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
}

View File

@ -0,0 +1,37 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
// Initialization succeeds as on an offline console: the title tears its whole web API layer down on
// an init failure and later dereferences it anyway. Requests made through it fail as offline.
int APS5_VABI _ZN3sce4Json11Initializer10initializeEPKNS0_13InitParameterE(void* self, const void* parameter) {
(void)self;
(void)parameter;
return 0;
}
int APS5_VABI _ZN3sce4Json11InitializerC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce4Json11InitializerD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce4Json12MemAllocatorC2Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce4Json12MemAllocatorD2Ev(void* self) {
(void)self;
return 0;
}
}

View File

@ -0,0 +1,10 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
int SceMsgDialogNativeModuleLoaded_nid_no_patch = 1;
}

View File

@ -2,54 +2,112 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <cstdio>
#include <map>
#include <memory>
#include <mutex>
// No network is emulated: pools, resolvers and epoll instances exist, but sockets cannot be
// created, so every socket operation fails with the guest's EBADF.
static constexpr int GUEST_EINTR = 4;
static constexpr int GUEST_EBADF = 9;
static constexpr int GUEST_EINVAL = 22;
static constexpr int GUEST_ENOSPC = 28;
static constexpr int GUEST_EAFNOSUPPORT = 47;
static constexpr int GUEST_ENETDOWN = 50;
static constexpr int GUEST_EHOSTUNREACH = 65;
static constexpr int GUEST_AF_INET = 2;
static thread_local int g_netErrno = 0;
static std::atomic<int> g_nextId{1};
struct Epoll {
std::mutex lock;
std::condition_variable changed;
bool aborted = false;
};
static std::mutex g_epollLock;
static std::map<int, std::shared_ptr<Epoll>> g_epolls;
static int Fail(int error) {
g_netErrno = error;
return static_cast<int>(0x80410100u | static_cast<unsigned>(error));
}
static std::shared_ptr<Epoll> FindEpoll(int eid) {
std::lock_guard lock(g_epollLock);
const auto found = g_epolls.find(eid);
return found == g_epolls.end() ? nullptr : found->second;
}
static void AbortEpoll(Epoll& epoll) {
{
std::lock_guard lock(epoll.lock);
epoll.aborted = true;
}
epoll.changed.notify_all();
}
extern "C" {
int APS5_VABI sceNetAccept(int s, void* addr, uint32_t* addrlen) {
(void)s;
(void)addr;
(void)addrlen;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
(void)addr;
(void)addrlen;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetBind_nid_postfix(int s, const void* addr, uint32_t addrlen) {
(void)s;
(void)addr;
(void)addrlen;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
(void)addr;
(void)addrlen;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetEpollControl(int eid, int op, int id, const NetEpollEvent* event) {
(void)eid;
(void)op;
(void)id;
(void)event;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)op;
(void)id;
(void)event;
if (!FindEpoll(eid)) return Fail(GUEST_EBADF);
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetEpollCreate(const char* name, int flags) {
(void)name;
(void)flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)name;
(void)flags;
const int id = g_nextId.fetch_add(1, std::memory_order_relaxed);
std::lock_guard lock(g_epollLock);
g_epolls[id] = std::make_shared<Epoll>();
return id;
}
int APS5_VABI sceNetEpollDestroy(int eid) {
(void)eid;
NotImplemented_nid_no_patch(__func__);
return 0;
std::lock_guard lock(g_epollLock);
const auto found = g_epolls.find(eid);
if (found == g_epolls.end()) return Fail(GUEST_EBADF);
AbortEpoll(*found->second);
g_epolls.erase(found);
return 0;
}
int APS5_VABI sceNetEpollWait(int eid, NetEpollEvent* events, int maxevents, int timeout) {
(void)eid;
(void)events;
(void)maxevents;
(void)timeout;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)events;
(void)maxevents;
auto epoll = FindEpoll(eid);
if (!epoll) return Fail(GUEST_EBADF);
std::unique_lock lock(epoll->lock);
const auto aborted = [&] { return epoll->aborted; };
if (timeout < 0) epoll->changed.wait(lock, aborted);
else epoll->changed.wait_for(lock, std::chrono::microseconds(timeout), aborted);
if (epoll->aborted) {
epoll->aborted = false;
return Fail(GUEST_EINTR);
}
return 0;
}
int APS5_VABI sceNetEtherNtostr(const NetEtherAddr* n, char* str, size_t len) {
@ -68,138 +126,214 @@ int APS5_VABI sceNetGetMacAddress(NetEtherAddr* addr, int flags) {
}
int APS5_VABI sceNetGetSockInfo(int s, void* info, int n, int flags) {
(void)s;
(void)info;
(void)n;
(void)flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
(void)info;
(void)n;
(void)flags;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetGetsockname(int s, void* addr, uint32_t* addrlen) {
(void)s;
(void)addr;
(void)addrlen;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
(void)addr;
(void)addrlen;
return Fail(GUEST_EBADF);
}
uint32_t APS5_VABI sceNetHtonl_nid_postfix(uint32_t host32) {
(void)host32;
NotImplemented_nid_no_patch(__func__);
return 0;
return __builtin_bswap32(host32);
}
uint16_t APS5_VABI sceNetHtons_nid_postfix(uint16_t host16) {
(void)host16;
NotImplemented_nid_no_patch(__func__);
return 0;
return __builtin_bswap16(host16);
}
const char* sceNetInetNtop(int af, const void* src, char* dst, uint32_t size) {
(void)af;
(void)src;
(void)dst;
(void)size;
NotImplemented_nid_no_patch(__func__);
return nullptr;
const char* APS5_VABI sceNetInetNtop(int af, const void* src, char* dst, uint32_t size) {
if (af != GUEST_AF_INET || !src || !dst) {
Fail(GUEST_EAFNOSUPPORT);
return nullptr;
}
const auto* bytes = static_cast<const uint8_t*>(src);
if (std::snprintf(dst, size, "%u.%u.%u.%u", bytes[0], bytes[1], bytes[2], bytes[3]) >= static_cast<int>(size)) {
Fail(GUEST_ENOSPC);
return nullptr;
}
return dst;
}
int APS5_VABI sceNetInetPton(int af, const char* src, void* dst) {
(void)af;
(void)src;
(void)dst;
NotImplemented_nid_no_patch(__func__);
return 0;
if (af != GUEST_AF_INET) return Fail(GUEST_EAFNOSUPPORT);
if (!src || !dst) return Fail(GUEST_EINVAL);
unsigned parts[4];
char trailing;
if (std::sscanf(src, "%u.%u.%u.%u%c", &parts[0], &parts[1], &parts[2], &parts[3], &trailing) != 4) return 0;
auto* bytes = static_cast<uint8_t*>(dst);
for (int index = 0; index < 4; ++index) {
if (parts[index] > 255) return 0;
bytes[index] = static_cast<uint8_t>(parts[index]);
}
return 1;
}
int APS5_VABI sceNetInit_nid_postfix(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
int APS5_VABI sceNetListen(int s, int backlog) {
(void)s;
(void)backlog;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
(void)backlog;
return Fail(GUEST_EBADF);
}
uint32_t APS5_VABI sceNetNtohl_nid_postfix(uint32_t net32) {
(void)net32;
NotImplemented_nid_no_patch(__func__);
return 0;
return __builtin_bswap32(net32);
}
uint16_t APS5_VABI sceNetNtohs_nid_postfix(uint16_t net16) {
(void)net16;
NotImplemented_nid_no_patch(__func__);
return 0;
return __builtin_bswap16(net16);
}
int APS5_VABI sceNetPoolCreate(const char* name, int size, int flags) {
(void)name;
(void)size;
(void)flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)name;
(void)flags;
if (size <= 0) return Fail(GUEST_EINVAL);
return g_nextId.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNetPoolDestroy(int memid) {
(void)memid;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)memid;
return 0;
}
int APS5_VABI sceNetResolverCreate(const char* name, int memid, int flags) {
(void)name;
(void)memid;
(void)flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)name;
(void)memid;
(void)flags;
return g_nextId.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNetResolverStartNtoa(int rid, const char* hostname, void* addr, int timeout, int retry, int flags) {
(void)rid;
(void)hostname;
(void)addr;
(void)timeout;
(void)retry;
(void)flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)rid;
(void)hostname;
(void)addr;
(void)timeout;
(void)retry;
(void)flags;
return Fail(GUEST_EHOSTUNREACH);
}
int APS5_VABI sceNetSetsockopt(int s, int level, int optname, const void* optval, uint32_t optlen) {
(void)s;
(void)level;
(void)optname;
(void)optval;
(void)optlen;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
(void)level;
(void)optname;
(void)optval;
(void)optlen;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetShutdown(int s, int how) {
(void)s;
(void)how;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
(void)how;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetSocket(const char* name, int family, int type, int protocol) {
(void)name;
(void)family;
(void)type;
(void)protocol;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)name;
(void)family;
(void)type;
(void)protocol;
return Fail(GUEST_ENETDOWN);
}
int APS5_VABI sceNetSocketClose(int s) {
(void)s;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)s;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetConnect(int s, const void* addr, uint32_t addrlen) {
(void)s;
(void)addr;
(void)addrlen;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetEpollAbort(int eid, int flags) {
(void)flags;
auto epoll = FindEpoll(eid);
if (!epoll) return Fail(GUEST_EBADF);
AbortEpoll(*epoll);
return 0;
}
int* APS5_VABI sceNetErrnoLoc(void) {
return &g_netErrno;
}
int APS5_VABI sceNetGetsockopt(int s, int level, int optname, void* optval, uint32_t* optlen) {
(void)s;
(void)level;
(void)optname;
(void)optval;
(void)optlen;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetRecv(int s, void* buf, size_t len, int flags) {
(void)s;
(void)buf;
(void)len;
(void)flags;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetRecvfrom(int s, void* buf, size_t len, int flags, void* from, uint32_t* fromlen) {
(void)s;
(void)buf;
(void)len;
(void)flags;
(void)from;
(void)fromlen;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetResolverDestroy(int rid) {
(void)rid;
return 0;
}
int APS5_VABI sceNetResolverStartAton(int rid, const void* addr, char* hostname, int len, int timeout, int retry, int flags) {
(void)rid;
(void)addr;
(void)hostname;
(void)len;
(void)timeout;
(void)retry;
(void)flags;
return Fail(GUEST_EHOSTUNREACH);
}
int APS5_VABI sceNetSend(int s, const void* msg, size_t len, int flags) {
(void)s;
(void)msg;
(void)len;
(void)flags;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetSendto(int s, const void* msg, size_t len, int flags, const void* to, uint32_t tolen) {
(void)s;
(void)msg;
(void)len;
(void)flags;
(void)to;
(void)tolen;
return Fail(GUEST_EBADF);
}
int APS5_VABI sceNetSocketAbort(int s, int flags) {
(void)s;
(void)flags;
return Fail(GUEST_EBADF);
}
}

View File

@ -2,67 +2,80 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <mutex>
// Network control reports an initialized but disconnected interface: no network is emulated.
static constexpr int SCE_NET_CTL_ERROR_CALLBACK_MAX = static_cast<int>(0x80412103);
static constexpr int SCE_NET_CTL_ERROR_INVALID_ID = static_cast<int>(0x80412105);
static constexpr int SCE_NET_CTL_ERROR_INVALID_ADDR = static_cast<int>(0x80412107);
static constexpr int SCE_NET_CTL_ERROR_NOT_CONNECTED = static_cast<int>(0x80412108);
static constexpr int NET_CTL_STATE_DISCONNECTED = 0;
static constexpr int MAX_CALLBACKS = 8;
static std::mutex g_callbackLock;
static NetCtlCallback g_callbacks[MAX_CALLBACKS] = {};
extern "C" {
int APS5_VABI sceNetCtlCheckCallback(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
int APS5_VABI sceNetCtlGetInfo(int code, NetCtlInfo* info) {
(void)code;
(void)info;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)code;
(void)info;
return SCE_NET_CTL_ERROR_NOT_CONNECTED;
}
int APS5_VABI sceNetCtlGetNatInfo(NetCtlNatInfo* nat_info) {
(void)nat_info;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)nat_info;
return SCE_NET_CTL_ERROR_NOT_CONNECTED;
}
int APS5_VABI sceNetCtlGetResult(int event_type, int* error_code) {
(void)event_type;
(void)error_code;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)event_type;
if (!error_code) return SCE_NET_CTL_ERROR_INVALID_ADDR;
*error_code = 0;
return 0;
}
int APS5_VABI sceNetCtlGetState(int* state) {
(void)state;
NotImplemented_nid_no_patch(__func__);
return 0;
if (!state) return SCE_NET_CTL_ERROR_INVALID_ADDR;
*state = NET_CTL_STATE_DISCONNECTED;
return 0;
}
int APS5_VABI sceNetCtlGetStateV6(int* state) {
(void)state;
NotImplemented_nid_no_patch(__func__);
return 0;
if (!state) return SCE_NET_CTL_ERROR_INVALID_ADDR;
*state = NET_CTL_STATE_DISCONNECTED;
return 0;
}
int APS5_VABI sceNetCtlInit(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
int APS5_VABI sceNetCtlRegisterCallback(NetCtlCallback func, void* arg, int* cid) {
(void)func;
(void)arg;
(void)cid;
NotImplemented_nid_no_patch(__func__);
return 0;
if (!func || !cid) return SCE_NET_CTL_ERROR_INVALID_ADDR;
std::lock_guard lock(g_callbackLock);
for (int index = 0; index < MAX_CALLBACKS; ++index) {
if (!g_callbacks[index]) {
g_callbacks[index] = func;
*cid = index;
return 0;
}
}
return SCE_NET_CTL_ERROR_CALLBACK_MAX;
}
void APS5_VABI sceNetCtlTerm(void) {
NotImplemented_nid_no_patch(__func__);
}
int APS5_VABI sceNetCtlUnregisterCallback(int cid) {
(void)cid;
NotImplemented_nid_no_patch(__func__);
return 0;
if (cid < 0 || cid >= MAX_CALLBACKS) return SCE_NET_CTL_ERROR_INVALID_ID;
std::lock_guard lock(g_callbackLock);
g_callbacks[cid] = nullptr;
return 0;
}
}

View File

@ -1,12 +1,67 @@
#include <cstdint>
#include <cstddef>
#include <cstring>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
namespace {
constexpr int COMMON_DIALOG_STATUS_NONE = 0;
constexpr int COMMON_DIALOG_STATUS_INITIALIZED = 1;
constexpr int COMMON_DIALOG_STATUS_FINISHED = 3;
constexpr int COMMON_DIALOG_RESULT_USER_CANCELED = 1;
constexpr int COMMON_DIALOG_ERROR_NOT_INITIALIZED = static_cast<int>(0x80B80003u);
constexpr int COMMON_DIALOG_ERROR_ALREADY_INITIALIZED = static_cast<int>(0x80B80004u);
constexpr int COMMON_DIALOG_ERROR_NOT_FINISHED = static_cast<int>(0x80B80006u);
constexpr int COMMON_DIALOG_ERROR_ARG_NULL = static_cast<int>(0x80B80009u);
int g_status = COMMON_DIALOG_STATUS_NONE;
}
extern "C" {
// The store dialog has nothing to show: every open finishes at once as cancelled by the user.
int APS5_VABI sceNpCommerceDialogInitialize() {
if (g_status != COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_ALREADY_INITIALIZED;
g_status = COMMON_DIALOG_STATUS_INITIALIZED;
return 0;
}
int APS5_VABI sceNpCommerceDialogOpen(const void* param) {
if (g_status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
if (param == nullptr) return COMMON_DIALOG_ERROR_ARG_NULL;
g_status = COMMON_DIALOG_STATUS_FINISHED;
return 0;
}
int APS5_VABI sceNpCommerceDialogUpdateStatus(void) {
NotImplemented_nid_no_patch(__func__);
return g_status;
}
int APS5_VABI sceNpCommerceDialogGetStatus(void) {
return g_status;
}
int APS5_VABI sceNpCommerceDialogGetResult(void* result) {
if (result == nullptr) return COMMON_DIALOG_ERROR_ARG_NULL;
if (g_status != COMMON_DIALOG_STATUS_FINISHED) return COMMON_DIALOG_ERROR_NOT_FINISHED;
// SceNpCommerceDialogResult: int32 result, bool authorized, then reserved bytes.
std::int32_t value = COMMON_DIALOG_RESULT_USER_CANCELED;
std::memcpy(result, &value, sizeof(value));
std::uint8_t authorized = 0;
std::memcpy(static_cast<std::uint8_t*>(result) + sizeof(value), &authorized, sizeof(authorized));
return 0;
}
int APS5_VABI sceNpCommerceDialogClose(void) {
if (g_status == COMMON_DIALOG_STATUS_NONE) return COMMON_DIALOG_ERROR_NOT_INITIALIZED;
g_status = COMMON_DIALOG_STATUS_FINISHED;
return 0;
}
int APS5_VABI sceNpCommerceDialogTerminate() {
g_status = COMMON_DIALOG_STATUS_NONE;
return 0;
}

View File

@ -0,0 +1,745 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
static constexpr int SCE_NP_WEBAPI_ERROR_UNAVAILABLE = static_cast<int>(0x80552901);
// Offline PSN: request entry points (API calls, transaction start/readData, factories) fail with
// SCE_NP_WEBAPI_ERROR_UNAVAILABLE; parameter bookkeeping succeeds; response accessors stay unimplemented
// because a failed request never produces a response.
extern "C" {
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V111UserFactory6createEPNS1_6Common10LibContextEPNS5_12IntrusivePtrINS3_4UserEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody18setStartSerialRankERKi() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody8setGroupERKNS3_5GroupE() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody8setLimitERKi() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody8setUsersERKNS1_6Common6VectorINS5_12IntrusivePtrINS3_4UserEEEEE() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V121GetRankingRequestBody9setOffsetERKi() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122GetRankingResponseBody10getEntriesEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody10setCommentEPKc() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody12setSmallDataEPKvm() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody15setNeedsTmpRankERKb() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody19setComparedDateTimeERK10SceRtcTick() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V122RecordScoreRequestBody7setPcIdERKi() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V128GetRankingRequestBodyFactory6createEPNS1_6Common10LibContextEPNS5_12IntrusivePtrINS3_21GetRankingRequestBodyEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V129RecordScoreRequestBodyFactory6createEPNS1_6Common10LibContextElPNS5_12IntrusivePtrINS3_22RecordScoreRequestBodyEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V14User12setAccountIdERKm() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V14User7setPcIdERKi() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi10getRankingEiRKNS4_21ParameterToGetRankingERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_22GetRankingResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRanking10initializeEPNS1_6Common10LibContextEi() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRanking24setgetRankingRequestBodyENS1_6Common12IntrusivePtrINS3_21GetRankingRequestBodyEEE() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRanking9terminateEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRankingC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi21ParameterToGetRankingD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi22getLargeDataByObjectIdEiRKNS4_33ParameterToGetLargeDataByObjectIdERNS1_6Common21DownStreamTransactionINS8_12IntrusivePtrINS4_37GetLargeDataByObjectIdResponseHeadersEEEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectId10initializeEPNS1_6Common10LibContextEPKc() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectId9terminateEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectIdC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V17ViewApi33ParameterToGetLargeDataByObjectIdD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi18getBoardDefinitionEiRKNS4_29ParameterToGetBoardDefinitionERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_30GetBoardDefinitionResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinition10initializeEPNS1_6Common10LibContextEi() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinition9terminateEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinitionC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19BoardsApi29ParameterToGetBoardDefinitionD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi11recordScoreEiRKNS4_22ParameterToRecordScoreERNS1_6Common11TransactionINS8_12IntrusivePtrINS3_23RecordScoreResponseBodyEEENSA_INS4_26RecordScoreResponseHeadersEEEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi15recordLargeDataEiRKNS4_26ParameterToRecordLargeDataERNS1_6Common19UpStreamTransactionINS8_12IntrusivePtrINS3_27RecordLargeDataResponseBodyEEENSA_INS8_18ResponseHeaderBaseEEEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScore10initializeEPNS1_6Common10LibContextEiNS6_12IntrusivePtrINS3_22RecordScoreRequestBodyEEE() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScore22setxPsnAtomicOperationENS5_19XPsnAtomicOperationE() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScore9terminateEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScoreC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi22ParameterToRecordScoreD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeData10initializeEPNS1_6Common10LibContextEiNS5_19XPsnAtomicOperationEPKc() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeData9terminateEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeDataC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi12Leaderboards2V19RecordApi26ParameterToRecordLargeDataD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi12downloadDataEiRKNS4_23ParameterToDownloadDataERNS1_6Common21DownStreamTransactionINS8_12IntrusivePtrINS4_27DownloadDataResponseHeadersEEEEE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadData10initializeEPNS1_6Common10LibContextEPKci() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadData9terminateEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadDataC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi17TitleCloudStorage2V17DataApi23ParameterToDownloadDataD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common10InitParamsC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common10InitParamsD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common10LibContextC1Ev(uint64_t* self) {
*self = 0;
return 0;
}
// Initialization succeeds as on an offline console (see libSceJson2); individual requests fail.
int APS5_VABI _ZN3sce2Np9CppWebApi6Common10initializeERKNS2_10InitParamsERNS2_10LibContextE(const void* params, uint64_t* context) {
(void)params;
if (context) *context = 1;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1ERS7_(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1ERS7_(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common13ConstIteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEED2Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE5startEPNS2_10LibContextE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE6finishEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE6finishEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE5startEPNS2_10LibContextEm() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE8sendDataEPKvm() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common19UpStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V127RecordLargeDataResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEE5startEPNS2_10LibContextE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEE6finishEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEE8readDataEPcm() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_12Leaderboards2V17ViewApi37GetLargeDataByObjectIdResponseHeadersEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEE5startEPNS2_10LibContextE() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEE6finishEv() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEE8readDataEPcm() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEEC1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common21DownStreamTransactionINS2_12IntrusivePtrINS1_17TitleCloudStorage2V17DataApi27DownloadDataResponseHeadersEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringC1EPNS2_10LibContextE(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common6StringD1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V14UserEEEE8pushBackERKS8_() {
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V14UserEEEEC1EPNS2_10LibContextE(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V14UserEEEED1Ev(void* self) {
(void)self;
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEE3endEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common6VectorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEE5beginEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEEppEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZN3sce2Np9CppWebApi6Common9terminateERNS2_10LibContextE(uint64_t* context) {
*context = 0;
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V122GetRankingResponseBody22getLastUpdatedDateTimeEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V123RecordScoreResponseBody10getTmpRankEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V123RecordScoreResponseBody16getTmpSerialRankEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody11getSortModeEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody13getEntryLimitEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody13getUpdateModeEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody13sortModeIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody15entryLimitIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody15updateModeIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody16getMaxScoreLimitEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody16getMinScoreLimitEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody18maxScoreLimitIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody18minScoreLimitIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody20getLargeDataNumLimitEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody21getLargeDataSizeLimitEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody22largeDataNumLimitIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V130GetBoardDefinitionResponseBody23largeDataSizeLimitIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry10getCommentEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry11getObjectIdEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry11getOnlineIdEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry12commentIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry12getAccountIdEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry12getSmallDataEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry13getSerialRankEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry13objectIdIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry14getHighestRankEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry14smallDataIsSetEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry20getHighestSerialRankEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry7getPcIdEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry7getRankEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V15Entry8getScoreEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi12Leaderboards2V19RecordApi26RecordScoreResponseHeaders24getXPsnAtomicOperationIdEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE11getResponseERS8_() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common11TransactionINS2_12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEENS4_INS2_18ResponseHeaderBaseEEEE11getResponseERS8_() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V121GetRankingRequestBodyEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122GetRankingResponseBodyEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V122RecordScoreRequestBodyEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V130GetBoardDefinitionResponseBodyEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V14UserEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V15EntryEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS1_12Leaderboards2V19RecordApi26RecordScoreResponseHeadersEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6BinaryEEptEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common12IntrusivePtrINS2_6VectorINS3_INS1_12Leaderboards2V15EntryEEEEEEdeEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common15TransactionBaseINS2_12IntrusivePtrINS1_12Leaderboards2V123RecordScoreResponseBodyEEENS4_INS6_9RecordApi26RecordScoreResponseHeadersEEEE18getResponseHeadersERSB_() {
return SCE_NP_WEBAPI_ERROR_UNAVAILABLE;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6Binary4sizeEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6Binary9getBinaryEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common6String5c_strEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEEdeEv() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI _ZNK3sce2Np9CppWebApi6Common8IteratorINS2_12IntrusivePtrINS1_12Leaderboards2V15EntryEEEEneERKS9_() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
}

View File

@ -3,36 +3,39 @@
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
// No add-on content is installed; the base game is the full SKU.
static constexpr int SCE_NP_ENTITLEMENT_ACCESS_ERROR_PARAMETER = static_cast<int>(0x80558003);
static constexpr int SCE_NP_ENTITLEMENT_ACCESS_ERROR_NOT_FOUND = static_cast<int>(0x80558007);
static constexpr uint32_t SKU_FLAG_FULL = 3;
extern "C" {
int APS5_VABI sceNpEntitlementAccessGetAddcontEntitlementInfo(uint32_t service_label, const NpUnifiedEntitlementLabel* entitlement_label, NpEntitlementAccessAddcontEntitlementInfo* info) {
(void)service_label;
(void)entitlement_label;
(void)info;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)service_label;
(void)entitlement_label;
(void)info;
return SCE_NP_ENTITLEMENT_ACCESS_ERROR_NOT_FOUND;
}
int APS5_VABI sceNpEntitlementAccessGetAddcontEntitlementInfoList(uint32_t service_label, NpEntitlementAccessAddcontEntitlementInfo* list, uint32_t list_num, uint32_t* hit_num) {
(void)service_label;
(void)list;
(void)list_num;
(void)hit_num;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)service_label;
(void)list;
(void)list_num;
if (!hit_num) return SCE_NP_ENTITLEMENT_ACCESS_ERROR_PARAMETER;
*hit_num = 0;
return 0;
}
int APS5_VABI sceNpEntitlementAccessGetSkuFlag(uint32_t* sku_flag) {
(void)sku_flag;
NotImplemented_nid_no_patch(__func__);
return 0;
if (!sku_flag) return SCE_NP_ENTITLEMENT_ACCESS_ERROR_PARAMETER;
*sku_flag = SKU_FLAG_FULL;
return 0;
}
int APS5_VABI sceNpEntitlementAccessInitialize(const NpEntitlementAccessInitParam* init_param, NpEntitlementAccessBootParam* boot_param) {
(void)init_param;
(void)boot_param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)init_param;
(void)boot_param;
return 0;
}
}

View File

@ -2,18 +2,25 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
// PSN is not emulated: the user is reported as signed out and online queries fail.
static constexpr int SCE_NP_ERROR_INVALID_ARGUMENT = static_cast<int>(0x80550003);
static constexpr int SCE_NP_ERROR_SIGNED_OUT = static_cast<int>(0x80550006);
static constexpr uint32_t NP_STATE_SIGNED_OUT = 1;
static constexpr int NP_POLL_ASYNC_FINISHED = 0;
static std::atomic<int> g_nextRequest{1};
extern "C" {
int APS5_VABI sceNpAbortRequest(int req_id) {
(void)req_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
return 0;
}
int APS5_VABI sceNpCheckCallback(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
int APS5_VABI sceNpCheckNpAvailability(int req_id, const char* user, void* result) {
@ -32,28 +39,24 @@ int APS5_VABI sceNpCheckNpReachability(int req_id, int user_id) {
}
int APS5_VABI sceNpCheckPremium(int req_id, const NpCheckPremiumParameter* param, NpCheckPremiumResult* result) {
(void)req_id;
(void)param;
(void)result;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
(void)param;
(void)result;
return SCE_NP_ERROR_SIGNED_OUT;
}
int APS5_VABI sceNpCreateAsyncRequest(const NpCreateAsyncRequestParameter* param) {
(void)param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)param;
return g_nextRequest.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpCreateRequest(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return g_nextRequest.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpDeleteRequest(int req_id) {
(void)req_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
return 0;
}
int APS5_VABI sceNpGetAccountAge(int req_id, int user_id, uint8_t* age) {
@ -65,17 +68,15 @@ int APS5_VABI sceNpGetAccountAge(int req_id, int user_id, uint8_t* age) {
}
int APS5_VABI sceNpGetAccountCountryA(int user_id, void* country_code) {
(void)user_id;
(void)country_code;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_id;
(void)country_code;
return SCE_NP_ERROR_SIGNED_OUT;
}
int APS5_VABI sceNpGetAccountIdA(int user_id, uint64_t* account_id) {
(void)user_id;
(void)account_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_id;
(void)account_id;
return SCE_NP_ERROR_SIGNED_OUT;
}
int APS5_VABI sceNpGetNpId(int user_id, NpId* np_id) {
@ -93,17 +94,16 @@ int APS5_VABI sceNpGetNpReachabilityState(int user_id, uint32_t* state) {
}
int APS5_VABI sceNpGetOnlineId(int user_id, NpOnlineId* online_id) {
(void)user_id;
(void)online_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_id;
(void)online_id;
return SCE_NP_ERROR_SIGNED_OUT;
}
int APS5_VABI sceNpGetState(int user_id, uint32_t* state) {
(void)user_id;
(void)state;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_id;
if (!state) return SCE_NP_ERROR_INVALID_ARGUMENT;
*state = NP_STATE_SIGNED_OUT;
return 0;
}
int APS5_VABI sceNpHasSignedUp(int user_id, bool* has_signed_up) {
@ -114,10 +114,9 @@ int APS5_VABI sceNpHasSignedUp(int user_id, bool* has_signed_up) {
}
int APS5_VABI sceNpPollAsync(int req_id, int* result) {
(void)req_id;
(void)result;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)req_id;
if (result) *result = SCE_NP_ERROR_SIGNED_OUT;
return NP_POLL_ASYNC_FINISHED;
}
void APS5_VABI sceNpRegisterGamePresenceCallback(void* callback, void* userdata) {
@ -161,10 +160,9 @@ int APS5_VABI sceNpSetContentRestriction(const NpContentRestriction* restriction
}
int APS5_VABI sceNpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret) {
(void)title_id;
(void)title_secret;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)title_id;
(void)title_secret;
return 0;
}
int APS5_VABI sceNpUnregisterStateCallback(void) {
@ -172,4 +170,27 @@ int APS5_VABI sceNpUnregisterStateCallback(void) {
return 0;
}
int APS5_VABI sceNpGetAccountLanguage2(int req_id, int user_id, void* language) {
(void)req_id;
(void)user_id;
(void)language;
return SCE_NP_ERROR_SIGNED_OUT;
}
int APS5_VABI sceNpNotifyPremiumFeature(const void* param) {
(void)param;
return 0;
}
int APS5_VABI sceNpRegisterStateCallbackA(void* callback, void* userdata) {
(void)userdata;
if (!callback) return SCE_NP_ERROR_INVALID_ARGUMENT;
return 1;
}
int APS5_VABI sceNpUnregisterStateCallbackA(int callback_id) {
(void)callback_id;
return 0;
}
}

View File

@ -2,13 +2,47 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
// Peer-to-peer signaling needs the network: contexts exist, but sessions never activate.
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT = static_cast<int>(0x80552D02);
static constexpr int SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE = static_cast<int>(0x80552D06);
static std::atomic<uint32_t> g_nextContext{1};
extern "C" {
int APS5_VABI sceNpSessionSignalingInitialize(void* param) {
(void)param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)param;
return 0;
}
int APS5_VABI sceNpSessionSignalingActivateSession(void) {
return SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE;
}
int APS5_VABI sceNpSessionSignalingCreateContext2(const void* param, uint32_t* context_id) {
(void)param;
if (!context_id) return SCE_NP_SESSION_SIGNALING_ERROR_INVALID_ARGUMENT;
*context_id = g_nextContext.fetch_add(1, std::memory_order_relaxed);
return 0;
}
int APS5_VABI sceNpSessionSignalingDeactivate(uint32_t context_id) {
(void)context_id;
return 0;
}
int APS5_VABI sceNpSessionSignalingDestroyContext(uint32_t context_id) {
(void)context_id;
return 0;
}
int APS5_VABI sceNpSessionSignalingGetConnectionInfo(void) {
return SCE_NP_SESSION_SIGNALING_ERROR_UNAVAILABLE;
}
int APS5_VABI sceNpSessionSignalingTerminate(void) {
return 0;
}
}

View File

@ -0,0 +1,10 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
int SceNpUtilityModuleLoaded_nid_no_patch = 1;
}

View File

@ -2,142 +2,155 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
// The PSN web API has no service behind it: handles can be created, but requests fail.
static constexpr int SCE_NP_WEBAPI2_ERROR_INVALID_ARGUMENT = static_cast<int>(0x80553402);
static constexpr int SCE_NP_WEBAPI2_ERROR_UNAVAILABLE = static_cast<int>(0x80553406);
static std::atomic<int> g_nextHandle{1};
extern "C" {
int APS5_VABI sceNpWebApi2AbortRequest(int64_t request_id) {
(void)request_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
return 0;
}
int APS5_VABI sceNpWebApi2AddHttpRequestHeader(int64_t request_id, const char* field_name, const char* value) {
(void)request_id;
(void)field_name;
(void)value;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)field_name;
(void)value;
return 0;
}
void APS5_VABI sceNpWebApi2CheckTimeout(void) {
NotImplemented_nid_no_patch(__func__);
}
int APS5_VABI sceNpWebApi2CreateRequest(int user_context_id, const char* api_group, const char* path, const char* method, const void* content_parameter, int64_t* request_id) {
(void)user_context_id;
(void)api_group;
(void)path;
(void)method;
(void)content_parameter;
(void)request_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_context_id;
(void)api_group;
(void)path;
(void)method;
(void)content_parameter;
if (!request_id) return SCE_NP_WEBAPI2_ERROR_INVALID_ARGUMENT;
*request_id = g_nextHandle.fetch_add(1, std::memory_order_relaxed);
return 0;
}
int APS5_VABI sceNpWebApi2CreateUserContext(int lib_ctx_id, int user_id) {
(void)lib_ctx_id;
(void)user_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_ctx_id;
(void)user_id;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpWebApi2DeleteRequest(int64_t request_id) {
(void)request_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
return 0;
}
int APS5_VABI sceNpWebApi2DeleteUserContext(int user_context_id) {
(void)user_context_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_context_id;
return 0;
}
int APS5_VABI sceNpWebApi2GetHttpResponseHeaderValue(int64_t request_id, const char* field_name, char* value, size_t value_size) {
(void)request_id;
(void)field_name;
(void)value;
(void)value_size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)field_name;
(void)value;
(void)value_size;
return SCE_NP_WEBAPI2_ERROR_UNAVAILABLE;
}
int APS5_VABI sceNpWebApi2GetHttpResponseHeaderValueLength(int64_t request_id, const char* field_name, size_t* value_length) {
(void)request_id;
(void)field_name;
(void)value_length;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)field_name;
(void)value_length;
return SCE_NP_WEBAPI2_ERROR_UNAVAILABLE;
}
int APS5_VABI sceNpWebApi2Initialize(int lib_http_ctx_id, size_t pool_size) {
(void)lib_http_ctx_id;
(void)pool_size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_http_ctx_id;
(void)pool_size;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpWebApi2PushEventCreateFilter(int lib_ctx_id, int handle_id, const char* np_service_name, uint32_t np_service_label, const void* filter_param, size_t filter_param_num) {
(void)lib_ctx_id;
(void)handle_id;
(void)np_service_name;
(void)np_service_label;
(void)filter_param;
(void)filter_param_num;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_ctx_id;
(void)handle_id;
(void)np_service_name;
(void)np_service_label;
(void)filter_param;
(void)filter_param_num;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpWebApi2PushEventCreateHandle(int lib_ctx_id) {
(void)lib_ctx_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_ctx_id;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpWebApi2PushEventDeleteHandle(int lib_ctx_id, int handle_id) {
(void)lib_ctx_id;
(void)handle_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_ctx_id;
(void)handle_id;
return 0;
}
int APS5_VABI sceNpWebApi2PushEventDeletePushContext(int user_context_id, const void* push_context_id) {
(void)user_context_id;
(void)push_context_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_context_id;
(void)push_context_id;
return 0;
}
int APS5_VABI sceNpWebApi2PushEventRegisterCallback(int user_context_id, int filter_id, void* callback, void* user_arg) {
(void)user_context_id;
(void)filter_id;
(void)callback;
(void)user_arg;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)user_context_id;
(void)filter_id;
(void)callback;
(void)user_arg;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpWebApi2ReadData(int64_t request_id, void* data, size_t size) {
(void)request_id;
(void)data;
(void)size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)data;
(void)size;
return SCE_NP_WEBAPI2_ERROR_UNAVAILABLE;
}
int APS5_VABI sceNpWebApi2SendRequest(int64_t request_id, const void* data, size_t data_size, NpWebApi2ResponseInformationOption* response_info_option) {
(void)request_id;
(void)data;
(void)data_size;
(void)response_info_option;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)request_id;
(void)data;
(void)data_size;
(void)response_info_option;
return SCE_NP_WEBAPI2_ERROR_UNAVAILABLE;
}
int APS5_VABI sceNpWebApi2Terminate(int lib_ctx_id) {
(void)lib_ctx_id;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)lib_ctx_id;
return 0;
}
int APS5_VABI sceNpWebApi2PushEventCreatePushContext() {
return SCE_NP_WEBAPI2_ERROR_UNAVAILABLE;
}
int APS5_VABI sceNpWebApi2PushEventDeleteFilter() {
return 0;
}
int APS5_VABI sceNpWebApi2PushEventRegisterPushContextCallback() {
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceNpWebApi2PushEventStartPushContextCallback() {
return 0;
}
int APS5_VABI sceNpWebApi2PushEventUnregisterCallback() {
return 0;
}
int APS5_VABI sceNpWebApi2PushEventUnregisterPushContextCallback() {
return 0;
}
}

View File

@ -87,12 +87,14 @@ int APS5_VABI scePadOpen_nid_postfix(int userId, int type, int index, const void
return PAD_HANDLE;
}
int APS5_VABI scePadReadState(int handle, PadData* data);
int APS5_VABI scePadRead_nid_postfix(int handle, PadData* data, int num) {
(void)handle;
(void)data;
(void)num;
NotImplemented_nid_no_patch(__func__);
return 0;
// The title drains the queued states; one current state is reported per call.
if (data == nullptr || num <= 0) APS5_INVALID_ARG_EX;
const int result = scePadReadState(handle, data);
if (result != 0) return result;
return 1;
}
int APS5_VABI scePadReadState(int handle, PadData* data) {

View File

@ -2,31 +2,86 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <fstream>
#include <iterator>
#include <regex>
#include <set>
#include <string>
// The game is fully installed on the host, so every chunk is local and nothing is pending.
static constexpr int SCE_PLAYGO_ERROR_BAD_POINTER = static_cast<int>(0x80B20004);
static constexpr int SCE_PLAYGO_ERROR_BAD_HANDLE = static_cast<int>(0x80B20005);
static constexpr int PLAYGO_HANDLE = 1;
static constexpr int8_t PLAYGO_LOCUS_LOCAL_FAST = 3;
static constexpr int32_t PLAYGO_INSTALL_SPEED_FULL = 2;
static int32_t g_installSpeed = PLAYGO_INSTALL_SPEED_FULL;
static constexpr int SCE_PLAYGO_ERROR_BAD_CHUNK_ID = static_cast<int>(0x80B2000C);
static constexpr int SCE_PLAYGO_ERROR_BAD_SIZE = static_cast<int>(0x80B2000D);
// The package's chunk table is not part of the dump, so the chunk set comes from the title's
// playgo-chunkdefs.xml: every listed chunk plus chunks 0 through the default chunk. Games probe
// chunk IDs and size arrays from the result, so unknown IDs must be rejected.
static const std::set<uint16_t>& ValidChunks() {
static const std::set<uint16_t> chunks = [] {
std::set<uint16_t> result{0};
std::ifstream file(ResolvePath_nid_no_patch("/app0/playgo-chunkdefs.xml"));
if (!file) return result;
const std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
static const std::regex chunk(R"re(<chunk\s+id="(\d+)")re");
for (auto it = std::sregex_iterator(text.begin(), text.end(), chunk); it != std::sregex_iterator(); ++it)
result.insert(static_cast<uint16_t>(std::stoul((*it)[1].str())));
static const std::regex defaultChunk(R"re(default_chunk="(\d+)")re");
std::smatch match;
if (std::regex_search(text, match, defaultChunk)) {
const auto last = std::stoul(match[1].str());
for (unsigned long id = 0; id <= last && id <= 0xFFFF; ++id) result.insert(static_cast<uint16_t>(id));
}
return result;
}();
return chunks;
}
static int ValidateChunks(const uint16_t* chunk_ids, uint32_t number_of_entries) {
if (!chunk_ids) return SCE_PLAYGO_ERROR_BAD_POINTER;
if (number_of_entries == 0) return SCE_PLAYGO_ERROR_BAD_SIZE;
const auto& valid = ValidChunks();
for (uint32_t index = 0; index < number_of_entries; ++index)
if (!valid.contains(chunk_ids[index])) return SCE_PLAYGO_ERROR_BAD_CHUNK_ID;
return 0;
}
extern "C" {
int APS5_VABI scePlayGoClose(int handle) {
(void)handle;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
return 0;
}
int APS5_VABI scePlayGoGetChunkId(int handle, uint16_t* out_chunk_id_list, uint32_t number_of_entries, uint32_t* out_entries) {
(void)handle;
(void)out_chunk_id_list;
(void)number_of_entries;
(void)out_entries;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
if (!out_entries) return SCE_PLAYGO_ERROR_BAD_POINTER;
const auto& valid = ValidChunks();
if (!out_chunk_id_list) {
*out_entries = static_cast<uint32_t>(valid.size());
return 0;
}
uint32_t written = 0;
for (const auto id : valid) {
if (written == number_of_entries) break;
out_chunk_id_list[written++] = id;
}
*out_entries = written;
return 0;
}
int APS5_VABI scePlayGoGetEta(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries, int64_t* out_eta) {
(void)handle;
(void)chunk_ids;
(void)number_of_entries;
(void)out_eta;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
if (!out_eta) return SCE_PLAYGO_ERROR_BAD_POINTER;
if (const int error = ValidateChunks(chunk_ids, number_of_entries)) return error;
*out_eta = 0;
return 0;
}
int APS5_VABI scePlayGoGetInstallChunkId(int handle, uint16_t* out_chunk_id_list, uint32_t number_of_entries, uint32_t* out_entries) {
@ -39,10 +94,10 @@ int APS5_VABI scePlayGoGetInstallChunkId(int handle, uint16_t* out_chunk_id_list
}
int APS5_VABI scePlayGoGetInstallSpeed(int handle, int32_t* out_speed) {
(void)handle;
(void)out_speed;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
if (!out_speed) return SCE_PLAYGO_ERROR_BAD_POINTER;
*out_speed = g_installSpeed;
return 0;
}
int APS5_VABI scePlayGoGetLanguageMask(int handle, uint64_t* out_language_mask) {
@ -53,83 +108,76 @@ int APS5_VABI scePlayGoGetLanguageMask(int handle, uint64_t* out_language_mask)
}
int APS5_VABI scePlayGoGetLocus(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries, int8_t* out_loci) {
(void)handle;
(void)chunk_ids;
(void)number_of_entries;
(void)out_loci;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
if (!out_loci) return SCE_PLAYGO_ERROR_BAD_POINTER;
if (const int error = ValidateChunks(chunk_ids, number_of_entries)) return error;
for (uint32_t index = 0; index < number_of_entries; ++index) out_loci[index] = PLAYGO_LOCUS_LOCAL_FAST;
return 0;
}
int APS5_VABI scePlayGoGetOptionalChunk(int handle, int32_t type, PlayGoOptionalChunk* option) {
(void)handle;
(void)type;
(void)option;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
(void)type;
if (!option) return SCE_PLAYGO_ERROR_BAD_POINTER;
option->bitmask = 0;
return 0;
}
int APS5_VABI scePlayGoGetProgress(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries, PlayGoProgress* out_progress) {
(void)handle;
(void)chunk_ids;
(void)number_of_entries;
(void)out_progress;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
if (!out_progress) return SCE_PLAYGO_ERROR_BAD_POINTER;
if (const int error = ValidateChunks(chunk_ids, number_of_entries)) return error;
out_progress->progress_size = 1;
out_progress->total_size = 1;
return 0;
}
int APS5_VABI scePlayGoGetSupportedOptionalChunk(int handle, int32_t type, PlayGoOptionalChunk* option) {
(void)handle;
(void)type;
(void)option;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
(void)type;
if (!option) return SCE_PLAYGO_ERROR_BAD_POINTER;
option->bitmask = 0;
return 0;
}
int APS5_VABI scePlayGoGetToDoList(int handle, PlayGoToDo* out_todo_list, uint32_t number_of_entries, uint32_t* out_entries) {
(void)handle;
(void)out_todo_list;
(void)number_of_entries;
(void)out_entries;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
(void)out_todo_list;
(void)number_of_entries;
if (!out_entries) return SCE_PLAYGO_ERROR_BAD_POINTER;
*out_entries = 0;
return 0;
}
int APS5_VABI scePlayGoInitialize(const PlayGoInitParams* init) {
(void)init;
NotImplemented_nid_no_patch(__func__);
return 0;
if (!init) return SCE_PLAYGO_ERROR_BAD_POINTER;
return 0;
}
int APS5_VABI scePlayGoOpen(int* out_handle, const void* param) {
(void)out_handle;
(void)param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)param;
if (!out_handle) return SCE_PLAYGO_ERROR_BAD_POINTER;
*out_handle = PLAYGO_HANDLE;
return 0;
}
int APS5_VABI scePlayGoPrefetch(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries, int8_t minimum_locus) {
(void)handle;
(void)chunk_ids;
(void)number_of_entries;
(void)minimum_locus;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
(void)minimum_locus;
return ValidateChunks(chunk_ids, number_of_entries);
}
int APS5_VABI scePlayGoPrefetchOptionalChunk(int handle, int32_t type, const PlayGoOptionalChunk* option) {
(void)handle;
(void)type;
(void)option;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
(void)type;
(void)option;
return 0;
}
int APS5_VABI scePlayGoSetInstallSpeed(int handle, int32_t speed) {
(void)handle;
(void)speed;
NotImplemented_nid_no_patch(__func__);
return 0;
if (handle != PLAYGO_HANDLE) return SCE_PLAYGO_ERROR_BAD_HANDLE;
g_installSpeed = speed;
return 0;
}
int APS5_VABI scePlayGoSetToDoList(int handle, const PlayGoToDo* todo_list, uint32_t number_of_entries) {
@ -141,8 +189,7 @@ int APS5_VABI scePlayGoSetToDoList(int handle, const PlayGoToDo* todo_list, uint
}
int APS5_VABI scePlayGoTerminate(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
}

View File

@ -0,0 +1,28 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
int APS5_VABI scePngEncCreate() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI scePngEncDelete() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI scePngEncEncode() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI scePngEncQueryMemorySize() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
}

View File

@ -0,0 +1,86 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
extern "C" {
APS5_EXPORT("+2KpvixvL6E", scePsmlUnknown__P2KpvixvL6E);
int APS5_VABI scePsmlUnknown__P2KpvixvL6E() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("3WVD91e12ZQ", scePsmlUnknown_3WVD91e12ZQ);
int APS5_VABI scePsmlUnknown_3WVD91e12ZQ() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("AHalTX9wFZY", scePsmlUnknown_AHalTX9wFZY);
int APS5_VABI scePsmlUnknown_AHalTX9wFZY() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("ArakEpzsZo0", scePsmlUnknown_ArakEpzsZo0);
int APS5_VABI scePsmlUnknown_ArakEpzsZo0() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("FSGaTQze0UY", scePsmlUnknown_FSGaTQze0UY);
int APS5_VABI scePsmlUnknown_FSGaTQze0UY() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("GHna9-DvnUk", scePsmlUnknown_GHna9_MDvnUk);
int APS5_VABI scePsmlUnknown_GHna9_MDvnUk() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("GJY0MvuTcs8", scePsmlUnknown_GJY0MvuTcs8);
int APS5_VABI scePsmlUnknown_GJY0MvuTcs8() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("JaLBe0P3jSU", scePsmlUnknown_JaLBe0P3jSU);
int APS5_VABI scePsmlUnknown_JaLBe0P3jSU() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("LXq+6mIxpCw", scePsmlUnknown_LXq_P6mIxpCw);
int APS5_VABI scePsmlUnknown_LXq_P6mIxpCw() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("RUNLFro+qok", scePsmlUnknown_RUNLFro_Pqok);
int APS5_VABI scePsmlUnknown_RUNLFro_Pqok() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("eWoKNeB6V-k", scePsmlUnknown_eWoKNeB6V_Mk);
int APS5_VABI scePsmlUnknown_eWoKNeB6V_Mk() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("gxv3i+MTEzU", scePsmlUnknown_gxv3i_PMTEzU);
int APS5_VABI scePsmlUnknown_gxv3i_PMTEzU() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
APS5_EXPORT("jEevBXmagOQ", scePsmlUnknown_jEevBXmagOQ);
int APS5_VABI scePsmlUnknown_jEevBXmagOQ() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
}

View File

@ -1,5 +1,11 @@
#include <algorithm>
#include <atomic>
#include <cstddef>
#include <deque>
#include <fstream>
#include <map>
#include <mutex>
#include <vector>
#include <cstdint>
#include <cstring>
#include <filesystem>
@ -18,6 +24,24 @@ static std::string save_root() {
return std::string(SAVE_DIR);
}
// Events the title polls with sceSaveDataGetEventResult (a backup completes at once here), and the
// "save data memory" blobs (small per-slot memories the title reads and writes without mounting),
// persisted as files under the save root so they survive restarts.
static std::mutex g_state_mutex;
static std::deque<SaveDataEvent> g_events;
static std::map<std::uint32_t, std::vector<std::uint8_t>> g_memories;
constexpr std::uint32_t SAVE_DATA_EVENT_TYPE_BACKUP = 2;
static std::string memory_path(std::uint32_t slot) {
return save_root() + "/_memory_" + std::to_string(slot) + ".bin";
}
static void store_memory(std::uint32_t slot, const std::vector<std::uint8_t>& memory) {
std::filesystem::create_directories(save_root());
std::ofstream file(memory_path(slot), std::ios::binary | std::ios::trunc);
file.write(reinterpret_cast<const char*>(memory.data()), static_cast<std::streamsize>(memory.size()));
}
static bool dir_name_match(const char* str, const char* pattern) {
if (pattern == nullptr || pattern[0] == '\0') {
return true;
@ -51,9 +75,20 @@ static bool dir_name_match(const char* str, const char* pattern) {
extern "C" {
int APS5_VABI sceSaveDataBackup(const SaveDataBackup* backup) {
(void)backup;
NotImplemented_nid_no_patch(__func__);
return 0;
if (backup == nullptr || backup->dir_name == nullptr) {
throw std::runtime_error("sceSaveDataBackup: null argument");
}
// The system copies the save directory to its backup area asynchronously; the copy itself is
// not observable by the title, only its completion event.
SaveDataEvent event{};
event.type = SAVE_DATA_EVENT_TYPE_BACKUP;
event.error_code = SAVE_DATA_OK;
event.user_id = backup->user_id;
if (backup->title_id != nullptr) event.title_id = *backup->title_id;
event.dir_name = *backup->dir_name;
std::lock_guard lock(g_state_mutex);
g_events.push_back(event);
return SAVE_DATA_OK;
}
int APS5_VABI sceSaveDataCommit(const SaveDataCommitParam* param) {
@ -119,9 +154,16 @@ int APS5_VABI sceSaveDataDirNameSearch(const SaveDataDirNameSearchCond* cond, Sa
int APS5_VABI sceSaveDataGetEventResult(const void* event_param, SaveDataEvent* event) {
(void)event_param;
(void)event;
NotImplemented_nid_no_patch(__func__);
return 0;
if (event == nullptr) {
throw std::runtime_error("sceSaveDataGetEventResult: null event");
}
std::lock_guard lock(g_state_mutex);
if (g_events.empty()) {
return SAVE_DATA_ERROR_NOT_FOUND;
}
*event = g_events.front();
g_events.pop_front();
return SAVE_DATA_OK;
}
int APS5_VABI sceSaveDataGetMountInfo(const SaveDataMountPoint* mount_point, SaveDataMountInfo* info) {
@ -153,9 +195,25 @@ int APS5_VABI sceSaveDataGetParam(const SaveDataMountPoint* mount_point, uint32_
}
int APS5_VABI sceSaveDataGetSaveDataMemory2(SaveDataMemoryGet2* get_param) {
(void)get_param;
NotImplemented_nid_no_patch(__func__);
return 0;
if (get_param == nullptr) {
throw std::runtime_error("sceSaveDataGetSaveDataMemory2: null argument");
}
std::lock_guard lock(g_state_mutex);
const auto it = g_memories.find(get_param->slot_id);
if (it == g_memories.end()) {
return SAVE_DATA_ERROR_NOT_FOUND;
}
if (get_param->data != nullptr && get_param->data->buf != nullptr) {
const auto& memory = it->second;
if (get_param->data->offset > memory.size()) {
return SAVE_DATA_ERROR_PARAMETER;
}
const auto bytes = std::min(get_param->data->buf_size, memory.size() - get_param->data->offset);
std::memcpy(get_param->data->buf, memory.data() + get_param->data->offset, bytes);
}
if (get_param->param != nullptr) std::memset(get_param->param, 0, sizeof(SaveDataParam));
if (get_param->icon != nullptr) get_param->icon->data_size = 0;
return SAVE_DATA_OK;
}
int APS5_VABI sceSaveDataInitialize3(const void* init) {
@ -204,12 +262,10 @@ int APS5_VABI sceSaveDataMount3(const SaveDataMount3* mount, SaveDataMountResult
throw std::runtime_error("sceSaveDataMount3: invalid directory name");
}
const std::string real_path = save_root() + "/" + dirName;
const std::string mountPoint = "/" + real_path;
if (mountPoint.size() >= sizeof(mount_result->mount_point.data)) {
throw std::runtime_error("sceSaveDataMount3: directory path exceeds mount point capacity");
}
if (find_slot_by_mount_point(mountPoint.c_str()) != -1) {
return SAVE_DATA_ERROR_BUSY;
for (const auto& used : g_slots) {
if (used.used && used.real_path == real_path) {
return SAVE_DATA_ERROR_BUSY;
}
}
const bool exists = std::filesystem::is_directory(real_path);
if (create && exists) {
@ -225,6 +281,10 @@ int APS5_VABI sceSaveDataMount3(const SaveDataMount3* mount, SaveDataMountResult
if (create || create2) {
std::filesystem::create_directories(real_path);
}
// The title gets a short mount point (16 bytes on the PS5) and opens files under it; the
// path resolver maps it to the save directory, whose name may be far longer.
const std::string mountPoint = "/_sm/" + std::to_string(slot);
AddPathAlias_nid_no_patch(mountPoint.c_str(), std::filesystem::absolute(real_path).string().c_str());
g_slots[slot].used = true;
g_slots[slot].mount_point = mountPoint;
g_slots[slot].real_path = real_path;
@ -271,22 +331,61 @@ int APS5_VABI sceSaveDataSetParam(const SaveDataMountPoint* mount_point, uint32_
}
int APS5_VABI sceSaveDataSetSaveDataMemory2(const SaveDataMemorySet2* set_param) {
(void)set_param;
NotImplemented_nid_no_patch(__func__);
return 0;
if (set_param == nullptr) {
throw std::runtime_error("sceSaveDataSetSaveDataMemory2: null argument");
}
std::lock_guard lock(g_state_mutex);
const auto it = g_memories.find(set_param->slot_id);
if (it == g_memories.end()) {
return SAVE_DATA_ERROR_NOT_FOUND;
}
auto& memory = it->second;
if (set_param->data != nullptr) {
const auto count = set_param->data_num == 0 ? 1u : set_param->data_num;
for (std::uint32_t i = 0; i < count; ++i) {
const auto& data = set_param->data[i];
if (data.buf == nullptr) continue;
if (data.offset > memory.size() || data.buf_size > memory.size() - data.offset) {
return SAVE_DATA_ERROR_PARAMETER;
}
std::memcpy(memory.data() + data.offset, data.buf, data.buf_size);
}
}
store_memory(set_param->slot_id, memory);
return SAVE_DATA_OK;
}
int APS5_VABI sceSaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2* setup_param, SaveDataMemorySetupResult* result) {
(void)setup_param;
(void)result;
NotImplemented_nid_no_patch(__func__);
return 0;
if (setup_param == nullptr) {
throw std::runtime_error("sceSaveDataSetupSaveDataMemory2: null argument");
}
std::lock_guard lock(g_state_mutex);
auto& memory = g_memories[setup_param->slot_id];
std::size_t existed = 0;
if (memory.empty()) {
std::ifstream file(memory_path(setup_param->slot_id), std::ios::binary);
if (file) {
memory.assign(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
existed = memory.size();
}
} else {
existed = memory.size();
}
if (memory.size() < setup_param->memory_size) {
memory.resize(setup_param->memory_size, 0);
}
if (existed == 0) store_memory(setup_param->slot_id, memory);
if (result != nullptr) {
std::memset(result, 0, sizeof(*result));
result->existed_memory_size = existed;
}
return SAVE_DATA_OK;
}
int APS5_VABI sceSaveDataSyncSaveDataMemory(const void* sync_param) {
(void)sync_param;
NotImplemented_nid_no_patch(__func__);
return 0;
// Every Set already reached the file; nothing is buffered.
return SAVE_DATA_OK;
}
int APS5_VABI sceSaveDataTerminate(void) {
@ -316,6 +415,7 @@ int APS5_VABI sceSaveDataUmount2(uint32_t mode, const SaveDataMountPoint* mount_
if (slot == -1) {
return SAVE_DATA_ERROR_NOT_MOUNTED;
}
RemovePathAlias_nid_no_patch(g_slots[slot].mount_point.c_str());
g_slots[slot] = MountSlot{};
return SAVE_DATA_OK;
}

View File

@ -3,6 +3,8 @@
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
// Capture and sharing are not emulated; policy and parameter calls are accepted.
extern "C" {
int APS5_VABI sceShareCaptureScreenshot(const void* param, int32_t* req_id) {
@ -20,15 +22,13 @@ int APS5_VABI sceShareCaptureVideoClip(const void* param, int32_t* req_id) {
}
int APS5_VABI sceShareFeaturePermit(uint32_t feature_flags) {
(void)feature_flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)feature_flags;
return 0;
}
int APS5_VABI sceShareFeatureProhibit(uint32_t feature_flags) {
(void)feature_flags;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)feature_flags;
return 0;
}
int APS5_VABI sceShareGetCurrentStatus(uint32_t feature_flag, ShareCurrentStatus* status) {
@ -39,11 +39,10 @@ int APS5_VABI sceShareGetCurrentStatus(uint32_t feature_flag, ShareCurrentStatus
}
int APS5_VABI sceShareInitialize(size_t heap_size, int thread_priority, uint64_t affinity_mask) {
(void)heap_size;
(void)thread_priority;
(void)affinity_mask;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)heap_size;
(void)thread_priority;
(void)affinity_mask;
return 0;
}
int APS5_VABI sceShareOpenMenuForContent(const void* content_id) {
@ -53,43 +52,37 @@ int APS5_VABI sceShareOpenMenuForContent(const void* content_id) {
}
int APS5_VABI sceShareRegisterContentEventCallback(void* callback, void* user_data) {
(void)callback;
(void)user_data;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)callback;
(void)user_data;
return 0;
}
int APS5_VABI sceShareSetCaptureSource(uint32_t feature_flags, const void* tap_point) {
(void)feature_flags;
(void)tap_point;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)feature_flags;
(void)tap_point;
return 0;
}
int APS5_VABI sceShareSetContentParam(const char* content_param) {
(void)content_param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)content_param;
return 0;
}
int APS5_VABI sceShareSetScreenshotOverlayImage(const char* file_path, int32_t margin_x, int32_t margin_y, int32_t origin) {
(void)file_path;
(void)margin_x;
(void)margin_y;
(void)origin;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)file_path;
(void)margin_x;
(void)margin_y;
(void)origin;
return 0;
}
int APS5_VABI sceShareTerminate(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
int APS5_VABI sceShareUnregisterContentEventCallback(void* callback) {
(void)callback;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)callback;
return 0;
}
}

View File

@ -0,0 +1,88 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
// Capture and sharing are not emulated; policy and parameter calls are accepted.
extern "C" {
int APS5_VABI sceShareCaptureScreenshot(const void* param, int32_t* req_id) {
(void)param;
(void)req_id;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceShareCaptureVideoClip(const void* param, int32_t* req_id) {
(void)param;
(void)req_id;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceShareFeaturePermit(uint32_t feature_flags) {
(void)feature_flags;
return 0;
}
int APS5_VABI sceShareFeatureProhibit(uint32_t feature_flags) {
(void)feature_flags;
return 0;
}
int APS5_VABI sceShareGetCurrentStatus(uint32_t feature_flag, ShareCurrentStatus* status) {
(void)feature_flag;
(void)status;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceShareInitialize(size_t heap_size, int thread_priority, uint64_t affinity_mask) {
(void)heap_size;
(void)thread_priority;
(void)affinity_mask;
return 0;
}
int APS5_VABI sceShareOpenMenuForContent(const void* content_id) {
(void)content_id;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceShareRegisterContentEventCallback(void* callback, void* user_data) {
(void)callback;
(void)user_data;
return 0;
}
int APS5_VABI sceShareSetCaptureSource(uint32_t feature_flags, const void* tap_point) {
(void)feature_flags;
(void)tap_point;
return 0;
}
int APS5_VABI sceShareSetContentParam(const char* content_param) {
(void)content_param;
return 0;
}
int APS5_VABI sceShareSetScreenshotOverlayImage(const char* file_path, int32_t margin_x, int32_t margin_y, int32_t origin) {
(void)file_path;
(void)margin_x;
(void)margin_y;
(void)origin;
return 0;
}
int APS5_VABI sceShareTerminate(void) {
return 0;
}
int APS5_VABI sceShareUnregisterContentEventCallback(void* callback) {
(void)callback;
return 0;
}
}

View File

@ -2,6 +2,12 @@
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
// No network is emulated: contexts, templates and requests can be created, but any request
// that would touch the network fails with the library's network error.
static constexpr int ERROR_NETWORK = static_cast<int>(0x80435001);
static std::atomic<int> g_nextHandle{1};
extern "C" {
@ -20,13 +26,21 @@ int APS5_VABI sceSslGetCaCerts(int ssl_ctx_id, void* ca_certs) {
}
int APS5_VABI sceSslInit_nid_postfix(uint64_t pool_size) {
(void)pool_size;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)pool_size;
return g_nextHandle.fetch_add(1, std::memory_order_relaxed);
}
int APS5_VABI sceSslTerm_nid_postfix(int ssl_ctx_id) {
(void)ssl_ctx_id;
(void)ssl_ctx_id;
return 0;
}
int APS5_VABI sceSslClose() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
int APS5_VABI sceSslGetSerialNumber() {
NotImplemented_nid_no_patch(__func__);
return 0;
}

View File

@ -3,6 +3,12 @@
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
// No touch input is emulated: recognizers exist but never report events.
static constexpr int32_t GESTURE_HANDLE = 1;
static constexpr int SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT = static_cast<int>(0x80D10002);
static constexpr int SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE = static_cast<int>(0x80D10003);
static constexpr int SCE_SYSTEM_GESTURE_ERROR_INDEX_OUT_OF_ARRAY = static_cast<int>(0x80D10005);
extern "C" {
int APS5_VABI sceSystemGestureAppendTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
@ -13,24 +19,20 @@ int APS5_VABI sceSystemGestureAppendTouchRecognizer(int32_t gesture_handle, Syst
}
int APS5_VABI sceSystemGestureClose(int32_t gesture_handle) {
(void)gesture_handle;
NotImplemented_nid_no_patch(__func__);
return 0;
return gesture_handle == GESTURE_HANDLE ? 0 : SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
}
int APS5_VABI sceSystemGestureCreateTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer, int32_t type, const SystemGestureRectangle* rectangle, const void* param) {
(void)gesture_handle;
(void)recognizer;
(void)type;
(void)rectangle;
(void)param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)type;
(void)rectangle;
(void)param;
if (gesture_handle != GESTURE_HANDLE) return SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
if (!recognizer) return SCE_SYSTEM_GESTURE_ERROR_INVALID_ARGUMENT;
return 0;
}
int APS5_VABI sceSystemGestureFinalizePrimitiveTouchRecognizer(void) {
NotImplemented_nid_no_patch(__func__);
return 0;
return 0;
}
int APS5_VABI sceSystemGestureGetPrimitiveTouchEventByIndex(int32_t gesture_handle, uint32_t index, SystemGesturePrimitiveTouchEvent* event) {
@ -74,12 +76,11 @@ int APS5_VABI sceSystemGestureGetTouchEventByEventID(int32_t gesture_handle, con
}
int APS5_VABI sceSystemGestureGetTouchEventByIndex(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, uint32_t index, SystemGestureTouchEvent* event) {
(void)gesture_handle;
(void)recognizer;
(void)index;
(void)event;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)gesture_handle;
(void)recognizer;
(void)index;
(void)event;
return SCE_SYSTEM_GESTURE_ERROR_INDEX_OUT_OF_ARRAY;
}
int APS5_VABI sceSystemGestureGetTouchEvents(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, SystemGestureTouchEvent* event_buffer, uint32_t capacity_of_buffer, uint32_t* number_of_event) {
@ -93,10 +94,8 @@ int APS5_VABI sceSystemGestureGetTouchEvents(int32_t gesture_handle, const Syste
}
int APS5_VABI sceSystemGestureGetTouchEventsCount(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer) {
(void)gesture_handle;
(void)recognizer;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)recognizer;
return gesture_handle == GESTURE_HANDLE ? 0 : SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
}
int APS5_VABI sceSystemGestureGetTouchRecognizerInformation(int32_t gesture_handle, const SystemGestureTouchRecognizer* recognizer, SystemGestureTouchRecognizerInformation* information) {
@ -108,16 +107,14 @@ int APS5_VABI sceSystemGestureGetTouchRecognizerInformation(int32_t gesture_hand
}
int APS5_VABI sceSystemGestureInitializePrimitiveTouchRecognizer(const void* param) {
(void)param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)param;
return 0;
}
int32_t APS5_VABI sceSystemGestureOpen(int32_t input_type, const void* param) {
(void)input_type;
(void)param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)input_type;
(void)param;
return GESTURE_HANDLE;
}
int APS5_VABI sceSystemGestureRemoveTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
@ -147,17 +144,13 @@ int APS5_VABI sceSystemGestureUpdateAllTouchRecognizer(int32_t gesture_handle) {
}
int APS5_VABI sceSystemGestureUpdatePrimitiveTouchRecognizer(int32_t gesture_handle, const void* param) {
(void)gesture_handle;
(void)param;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)param;
return gesture_handle == GESTURE_HANDLE ? 0 : SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
}
int APS5_VABI sceSystemGestureUpdateTouchRecognizer(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer) {
(void)gesture_handle;
(void)recognizer;
NotImplemented_nid_no_patch(__func__);
return 0;
(void)recognizer;
return gesture_handle == GESTURE_HANDLE ? 0 : SCE_SYSTEM_GESTURE_ERROR_INVALID_HANDLE;
}
int APS5_VABI sceSystemGestureUpdateTouchRecognizerRectangle(int32_t gesture_handle, SystemGestureTouchRecognizer* recognizer, const SystemGestureRectangle* rectangle) {

View File

@ -13,9 +13,12 @@ int APS5_VABI sceSystemServiceDisableNoticeScreenSkipFlagAutoSet(void) {
}
int APS5_VABI sceSystemServiceGetDisplaySafeAreaInfo(SystemServiceDisplaySafeAreaInfo* info) {
(void)info;
NotImplemented_nid_no_patch(__func__);
return 0;
if (info == nullptr) {
return SYSTEM_SERVICE_ERROR_PARAMETER;
}
*info = SystemServiceDisplaySafeAreaInfo{};
info->ratio = 1.0f;
return SYSTEM_SERVICE_OK;
}
int APS5_VABI sceSystemServiceGetHdrToneMapLuminance(SystemServiceHdrToneMapLuminance* luminance) {
@ -25,9 +28,11 @@ int APS5_VABI sceSystemServiceGetHdrToneMapLuminance(SystemServiceHdrToneMapLumi
}
int APS5_VABI sceSystemServiceGetNoticeScreenSkipFlag(bool* value) {
(void)value;
NotImplemented_nid_no_patch(__func__);
return 0;
if (value == nullptr) {
return SYSTEM_SERVICE_ERROR_PARAMETER;
}
*value = false;
return SYSTEM_SERVICE_OK;
}
int APS5_VABI sceSystemServiceGetStatus(SystemServiceStatus* status) {
@ -76,8 +81,6 @@ int APS5_VABI sceSystemServiceReceiveEvent(SystemServiceEvent* event) {
if (event == nullptr) {
return SYSTEM_SERVICE_ERROR_PARAMETER;
}
event->event_type = -1;
std::memset(event->data, 0, sizeof(event->data));
return SYSTEM_SERVICE_ERROR_NO_EVENT;
}
@ -92,4 +95,9 @@ int APS5_VABI sceSystemServiceSetNoticeScreenSkipFlag(void) {
return 0;
}
int APS5_VABI sceSystemServiceLoadExec() {
NotImplemented_nid_no_patch(__func__);
return 0;
}
}

View File

@ -2,6 +2,7 @@
#include <cstdint>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include <atomic>
#include "prx/libSceUserService/UserService.hpp"
extern "C" {
@ -48,17 +49,37 @@ int APS5_VABI sceUserServiceGetAgeLevel(int user_id, uint32_t* age_level) {
return 0;
}
// The initial user is reported as logging in once; afterwards there are no user events.
int APS5_VABI sceUserServiceGetEvent(SceUserServiceEvent* event) {
(void)event;
NotImplemented_nid_no_patch(__func__);
return 0;
if (event == nullptr) {
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
}
static std::atomic<bool> loginReported{false};
if (loginReported.exchange(true)) {
return USER_SERVICE_ERROR_NO_EVENT;
}
constexpr std::uint32_t EventTypeLogin = 0;
event->event_type = EventTypeLogin;
event->user_id = USER_SERVICE_INITIAL_USER_ID;
return USER_SERVICE_OK;
}
int APS5_VABI sceUserServiceGetGamePresets(int user_id, UserServiceGamePresets* presets) {
(void)user_id;
(void)presets;
NotImplemented_nid_no_patch(__func__);
return 0;
// System-wide game presets (difficulty, view inversion, subtitles, audio language) of the user's
// profile. A fresh console has none set: every field is 0, "not specified", and the title falls
// back to its own defaults. this_size is the caller's.
if (presets == nullptr || user_id != USER_SERVICE_INITIAL_USER_ID) {
return USER_SERVICE_ERROR_INVALID_ARGUMENT;
}
presets->difficulty = 0;
presets->priority = 0;
presets->invert_vertical_view_for_1st_person_view = 0;
presets->invert_horizontal_view_for_1st_person_view = 0;
presets->invert_vertical_view_for_3rd_person_view = 0;
presets->invert_horizontal_view_for_3rd_person_view = 0;
presets->display_sub_titles = 0;
presets->audio_language = 0;
return USER_SERVICE_OK;
}
int APS5_VABI sceUserServiceGetInitialUser(int* user_id) {
@ -108,4 +129,12 @@ int APS5_VABI sceUserServiceTerminate(void) {
return USER_SERVICE_OK;
}
// No PSN account exists, so the platform privacy setting reports the feature as not permitted.
int APS5_VABI sceUserServiceGetPlatformPrivacyWs1(int32_t user_id, int32_t* value) {
(void)user_id;
if (!value) return static_cast<int>(0x80960002);
*value = 0;
return 0;
}
}

View File

@ -1,4 +1,5 @@
add_library(libSceVideoOut SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/Unimplemented.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Event.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Output.cpp

View File

@ -0,0 +1,20 @@
#include <cstdint>
#include <cstddef>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include "prx/libSceVideoOut/include/Output.hpp"
#include <stdexcept>
extern "C" {
int APS5_VABI sceVideoOutAdjustColor_(int handle, const VideoOutColorSettings* settings, uint32_t settings_size) {
if (settings_size < sizeof(VideoOutColorSettings)) throw std::runtime_error("sceVideoOutAdjustColor_: VIDEO_OUT_ERROR_INVALID_VALUE");
return sceVideoOutAdjustColor(handle, settings);
}
int APS5_VABI sceVideoOutColorSettingsSetGamma_(VideoOutColorSettings* settings, float gamma, uint32_t settings_size) {
if (settings_size < sizeof(VideoOutColorSettings)) throw std::runtime_error("sceVideoOutColorSettingsSetGamma_: VIDEO_OUT_ERROR_INVALID_VALUE");
return sceVideoOutColorSettingsSetGamma(settings, gamma);
}
}

View File

@ -172,7 +172,8 @@ public:
std::shared_ptr<VideoOutConfig> GetConfig(int handle);
bool IsOpen(int handle);
void SubmitFlip(int handle, int index, int flipMode, int64_t flipArg);
// 0, or VIDEO_OUT_ERROR_FLIP_QUEUE_FULL when the title has VIDEO_OUT_FLIP_QUEUE_CAPACITY flips pending.
int SubmitFlip(int handle, int index, int flipMode, int64_t flipArg);
private:
bool close(int handle);

View File

@ -155,12 +155,10 @@ int APS5_VABI sceVideoOutSubmitFlip(int handle, int index, int flipMode, int64_t
if (cfg == nullptr) {
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_HANDLE");
}
if (flipMode < VIDEO_OUT_FLIP_MODE_VSYNC || flipMode > VIDEO_OUT_FLIP_MODE_VSYNC_MULTI) {
// Every mode is presented at the next vsync; HSYNC/WINDOW variants only change tearing behaviour.
if (flipMode < VIDEO_OUT_FLIP_MODE_VSYNC || flipMode > 6) {
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_VALUE");
}
if (flipMode != VIDEO_OUT_FLIP_MODE_VSYNC) {
throw std::runtime_error(std::string(__func__) + ": flip mode not implemented");
}
if (index < VIDEO_OUT_BUFFER_INDEX_BLACK || index >= VIDEO_OUT_BUFFER_NUM_MAX) {
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_INDEX");
}
@ -174,8 +172,7 @@ int APS5_VABI sceVideoOutSubmitFlip(int handle, int index, int flipMode, int64_t
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_INDEX");
}
lock.unlock();
VideoOutDriver::Get().SubmitFlip(handle, index, flipMode, flipArg);
return 0;
return VideoOutDriver::Get().SubmitFlip(handle, index, flipMode, flipArg);
}
}

View File

@ -181,14 +181,14 @@ int APS5_VABI sceVideoOutSetWindowModeMargins(int handle, int top, int bottom) {
if (!VideoOutDriver::Get().IsOpen(handle)) {
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_HANDLE");
}
throw std::runtime_error(std::string(__func__) + " not implemented");
return 0;
}
int APS5_VABI sceVideoOutLatencyControlWaitBeforeInput(int handle) {
if (!VideoOutDriver::Get().IsOpen(handle)) {
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_HANDLE");
}
throw std::runtime_error(std::string(__func__) + " not implemented");
return 0;
}
int APS5_VABI sceVideoOutLatencyMeasureSetStartPoint(int handle, uint32_t point) {
@ -196,7 +196,7 @@ int APS5_VABI sceVideoOutLatencyMeasureSetStartPoint(int handle, uint32_t point)
if (!VideoOutDriver::Get().IsOpen(handle)) {
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_HANDLE");
}
throw std::runtime_error(std::string(__func__) + " not implemented");
return 0;
}
int APS5_VABI sceVideoOutColorSettingsSetGamma(VideoOutColorSettings* settings, float gamma) {
@ -218,7 +218,8 @@ int APS5_VABI sceVideoOutAdjustColor(int handle, const VideoOutColorSettings* se
if (cfg == nullptr) {
throw std::runtime_error(std::string(__func__) + ": VIDEO_OUT_ERROR_INVALID_HANDLE");
}
throw std::runtime_error(std::string(__func__) + " not implemented");
// Output gamma is accepted but not yet applied to presentation.
return 0;
}
}

View File

@ -1,5 +1,6 @@
#include <bit>
#include <chrono>
#include <cstdlib>
#include <limits>
#include <stdexcept>
@ -31,7 +32,8 @@ public:
VideoOutput(std::shared_ptr<VideoOutConfig> config, std::shared_ptr<FlipQueue> requests) : cfg(std::move(config)), queue(std::move(requests)) {}
std::shared_ptr<AgcDriver::IFlipRequest> Reserve(const AgcDriver::FlipInfo& info) override {
require(info.mode == VIDEO_OUT_FLIP_MODE_VSYNC, "unsupported flip mode");
// All flip modes are presented at the next vsync.
require(info.mode >= VIDEO_OUT_FLIP_MODE_VSYNC && info.mode <= 6, "unsupported flip mode");
require(info.index >= VIDEO_OUT_BUFFER_INDEX_BLACK && info.index < VIDEO_OUT_BUFFER_NUM_MAX, "invalid flip index");
auto request = std::make_shared<FlipRequest>();
request->cfg = cfg;
@ -119,6 +121,12 @@ void FlipRequest::GpuReady(const std::shared_ptr<AgcDriver::FrameTiming>& frameT
ready = true;
}
queue->changed.notify_all();
// The worker is done once the request is queued: hardware does not stall the command processor
// on a flip, and the title observes completion through flipPendingNum, which processFlip drops
// after presenting. A presentation failure reaches the worker through ReportFailure at its next
// packet. Debug aid: APS5_SYNC_FLIP=1 parks the worker until the presenter is done, as before.
static const bool syncFlip = std::getenv("APS5_SYNC_FLIP") != nullptr;
if (!syncFlip) return;
std::unique_lock lock(cfg->mutex);
cfg->vblankCond.wait(lock, [&] { return gpuComplete || cfg->failure || cfg->closing; });
checkConfig(*cfg);
@ -281,11 +289,15 @@ bool VideoOutDriver::IsOpen(int handle) {
return GetConfig(handle) != nullptr;
}
void VideoOutDriver::SubmitFlip(int handle, int index, int flipMode, int64_t flipArg) {
int VideoOutDriver::SubmitFlip(int handle, int index, int flipMode, int64_t flipArg) {
// A title that does not pace on flipPendingNum can run ahead of the presenter now that the queue
// worker no longer waits per flip; a full queue is the documented error, not a failure.
if (flipQueue->reservations.load() >= VIDEO_OUT_FLIP_QUEUE_CAPACITY) return VIDEO_OUT_ERROR_FLIP_QUEUE_FULL;
std::array<uint32_t, AgcDriver::FlipPacketWords> words{AgcDriver::FlipPacketHeader, static_cast<uint32_t>(handle), static_cast<uint32_t>(index), static_cast<uint32_t>(flipMode), static_cast<uint32_t>(static_cast<uint64_t>(flipArg)), static_cast<uint32_t>(static_cast<uint64_t>(flipArg) >> 32u)};
Packet packet{words.data(), static_cast<uint32_t>(words.size()), 0, {}};
const auto result = sceAgcDriverSubmitDcb(&packet);
require(result == 0, "driver rejected flip submission");
return 0;
}
void VideoOutDriver::triggerEvents(VideoOutConfig& cfg, int eventKind, void* triggerData) {
@ -406,12 +418,6 @@ void VideoOutDriver::presentLoop(std::stop_token token) {
PadInput padInput;
try {
while (!token.stop_requested()) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
require(event.type != SDL_QUIT, "window was closed");
padInput.HandleEvent(event, window);
}
padInput.Update();
{
std::unique_lock lock(flipQueue->mutex);
flipQueue->changed.wait_for(lock, std::chrono::milliseconds(10), [&] { return token.stop_requested() || flipQueue->failure || !flipQueue->requests.empty(); });
@ -422,6 +428,12 @@ void VideoOutDriver::presentLoop(std::stop_token token) {
flipQueue->requests.pop_front();
}
}
SDL_Event event;
while (SDL_PollEvent(&event)) {
require(event.type != SDL_QUIT, "window was closed");
padInput.HandleEvent(event, window);
}
padInput.Update();
if (current) {
require(current->timing != nullptr, "missing presentation timing");
const auto dequeued = AgcDriver::FrameTiming::Clock::now();
@ -451,6 +463,9 @@ void VideoOutDriver::presentLoop(std::stop_token token) {
} catch (...) {
auto error = std::current_exception();
if (!error) std::terminate();
// The driver learns first: the worker no longer waits for the presenter, so a title (or test)
// that sees the failed flip's counters must already find the failure in the driver.
AgcDriverReportFailure_nid_postfix(error);
PadReportInputFailure_nid_postfix(error);
if (current) current->Fail(error);
std::list<std::shared_ptr<FlipRequest>> failed;
@ -470,7 +485,6 @@ void VideoOutDriver::presentLoop(std::stop_token token) {
}
}
flipQueue->changed.notify_all();
AgcDriverReportFailure_nid_postfix(error);
}
}