AnyPS5/docs/dev/debt/libSceAmpr.md

5.9 KiB

libSceAmpr technical debt

Unknown function info

  • 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 use the emulator's own encoding with an 8-byte header, so Nop(n) takes 8 + 4n bytes where the console record is n dwords including its header (NopWithData(n): (n + 1) dwords). The measure functions agree with the appended sizes, but a title that pads to an exact offset or the end of the buffer with Nop(remaining / 4) gets SCE_AMPR_ERROR_BUFFER_FULL or a shifted offset. 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 (libSceAmpr) - signatures taken from the ampr_emu reimplementation, not confirmed on a title: sceAmprCommandBufferSetMarkerWithColor takes the color by pointer, the push and measure variants by value. Colors are not recorded

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. _Thrd_t is taken to be the guest pthread_t, as the std::_Pad::_Launch(pthread**) export suggests: _Thrd_join returns _Thrd_error (4) when pthread_join fails and stores the thread's return value truncated to int. _Thrd_join (32-bit store of the result, 0 or 4) and the spin lock (byte exchange loop, no yield) match 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_signal, _Cnd_init_with_name (libSceAmpr) - take a pointer to the handle slot like the libc _Cnd_* exports from #3079 and act on the same conditions. _Cnd_signal wakes one waiter and returns _Thrd_success (0), as _Cnd_broadcast does; whether the console maps a failing internal signal to _Thrd_error is not known. 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. Neither is confirmed on a PS5 libc.prx. _Thrd_id still throws: microsoft/STL returns an unsigned int thread id, but whether the PS5 returns the pthread_t or a kernel thread id, and at what width, is not known
  • std::_Pad (libSceAmpr) follows Dinkumware V6.00 thr/xthread and thr/threadcall.cpp of Visual C++ 2013 (crt.vc12 f1d47126), without console verification. The pad is taken to be that header's class with the console's pointer handles: a vtable pointer whose first slot is the pure virtual _Go(), then _Cnd_t at 0x8, _Mtx_t at 0x10 and bool _Started at 0x18, 32 bytes, the derived _LaunchPad target following it; the console's _Pad(const char*) and _Launch(const char*, pthread**)/_Launch(pthread_attr**, pthread**) overloads suggest named primitives and could mean another layout or vtable. _Launch starts the thread with pthread_create and default attributes (the console's _Thrd_start name, stack size and priority are unknown), its entry calls _Go() and returns the result as the exit code, and it does not run _Cnd_do_broadcast_at_thread_exit, which is absent here. A failing primitive throws the guest std::system_error that _Throw_C_error picks for its code, and a failing thread start the resource_unavailable_try_again one of _Thrd_startX; any pthread_create error counts, since the console's _Thrd_start result is unknown. A null pad or thread slot throws