Files

7.3 KiB

libSceAmpr technical debt

Silent stubs

Unknown function info

  • AMPR command buffer null arguments (libSceAmpr) - the result for a null command buffer is unknown for sceAmprCommandBufferConstructor, sceAmprAprCommandBufferConstructor, sceAmprCommandBufferReset and sceAmprCommandBufferSetBuffer; these return SCE_KERNEL_ERROR_EINVAL here, but the behavior has not been confirmed on a PS5.
  • AMPR WriteAddressFromCounterPairOnCompletion (libSceAmpr) - the pair of an even counter n is assumed to give counter n in the low 32 bits and n + 1 in the high 32 bits. Wait compare values, wait flush and counter index ranges follow the ampr_emu reimplementation; the flush is accepted and has no effect, as commands run in order
  • AMPR command buffer offsets (libSceAmpr) - recording with a current offset greater than the bound memory size throws before calculating remaining capacity or writing a command. This validates the emulator's own command-buffer encoding; the console's response to a corrupted opaque buffer object is unknown.
  • AMPR command sizes (libSceAmpr) - commands other than Nop use the emulator's own encoding with an 8-byte header, so their measured sizes are not the console's. Nop(n) occupies n dwords and NopWithData(n) (n + 1) dwords with the header word 0x5452000F | payloadDwords << 8 | (type & 0xF) << 12, and ConstructNop writes its word before the payload and zeroes the payload's padding, as observed from firmware 13.42's libSceAmpr.sprx (#10936); a null base is reported before the count or payload range. One console behaviour is not reproduced: NopWithData with data and ConstructNop write four zero bytes right after the payload even where they fall past the end of the record, and of the buffer; AnyPS5 stops at the record. The at-start flag of the _04_00 writes is ignored; commands run in order, each after the previous one completes
  • APR map begin and end (libSceAmpr) - as in ampr_emu, MapBegin/MapDirectBegin map when they run and MapEnd only closes the region; while a region is open a second begin and every completion write return EPERM, the at-start _04_00 writes are accepted
  • AMPR markers: colors are not recorded and command sizes use the host encoding. Native signatures confirm that set takes a color pointer and push/measure take the color value.
  • __cxa_call_unexpected (libSceAmpr) - takes the in-flight exception's unwind header and never returns, as libcxxabi 18.1.8 does. No std::set_unexpected is exported and the exception header's unexpected handler is never set, so the handler is always the default one, which calls std::terminate (cxa_default_handlers.cpp); it therefore forwards to libc's __cxa_call_terminate, which begins the catch and runs the current terminate handler. That matches libcxxabi except for which terminate handler runs: there std::terminate after __cxa_begin_catch (cxa_exception.cpp L470-L477) runs the handler saved in the caught exception's header (cxa_handlers.cpp L72-L93), which __cxa_throw and __cxa_init_primary_exception set to std::get_terminate() when the exception is thrown (cxa_exception.cpp L209-L214, L279), while here the current global handler runs, as AnyPS5's own std::terminate does. The two differ only if std::set_terminate was called between the throw and this call. A null header terminates because this emulator's libc __cxa_begin_catch terminates on null (libcxxabi does not define that case). Dynamic exception specifications that would let a replaced unexpected handler throw a permitted type are not modelled

Functional

  • sceAmprAmmGetUsageStatsData (libSceAmpr) fills the caller-sized 24-byte statistics structure with 512 page-table pool entries, no allocated entries, a zero high watermark and ring idle flags 0x7, the constants of KytyPS5; they are not measured on a console, and the real call is a pass-through to sceKernelMapperGetUsageStatsData per drakmor/ampr_emu, which this port has no kernel-side counterpart for.
  • Dinkumware thread exports (libSceAmpr) follow the Dinkumware threads library shipped with Visual C++ 2013 (cthread.c) and its atomic.c, microsoft/STL cthread.cpp and C11 Annex K, without console verification. The spin lock (byte exchange loop, no yield) matches that disassembly. The shared_ptr spin lock is one process-wide flag that yields while it spins. wcstombs_s is wcsrtombs_s with a fresh conversion state, so *retval excludes the terminating null as in Annex K, not as in the Microsoft CRT, and _TRUNCATE has no meaning.
  • _Cnd_init_with_name (libSceAmpr) - takes a pointer to the handle slot like the libc _Cnd_* exports from #3079 and acts on the same conditions. The signature _Cnd_init_with_name(_Cnd_t*, const char* name) is inferred from fpPS4 ps4_mtx_internal.pas, where the PS4 _Mtx_init is _Mtx_init_with_name with the name SceLibcI_Mtx and the name only reaches the pthread object; here it is _Cnd_init and the name, which may be null, is ignored. This is not confirmed on a PS5 libc.prx.