AnyPS5/docs/dev/debt/libSceAmpr.md

17 lines
5.9 KiB
Markdown

# libSceAmpr technical debt
### Unknown function info
- [AMPR WriteAddressFromCounterPairOnCompletion](../../../core/libs/prx/libSceAmpr/Export.cpp) (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](https://github.com/drakmor/ampr_emu) reimplementation; the flush is accepted and has no effect, as commands run in order
- [AMPR command buffer offsets](../../../core/libs/prx/libSceAmpr/Export.cpp) (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](../../../core/libs/prx/libSceAmpr/Export.cpp) (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](../../../core/libs/prx/libSceAmpr/Export.cpp) (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](../../../core/libs/prx/libSceAmpr/Export.cpp) (libSceAmpr) - signatures taken from the [ampr_emu](https://github.com/drakmor/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](../../../core/libs/prx/libSceAmpr/Export.cpp) (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](https://github.com/KytyPS5/KytyPS5/blob/main/src/libs/libAmpr.cpp); they are not measured on a console, and the real call is a pass-through to `sceKernelMapperGetUsageStatsData` per [drakmor/ampr_emu](https://github.com/drakmor/ampr_emu/blob/main/src/ampr_emu_amm.cpp), which this port has no kernel-side counterpart for.
- [Dinkumware thread exports](../../../core/libs/prx/libSceAmpr/Export.cpp) (libSceAmpr) follow the Dinkumware threads library shipped with [Visual C++ 2013](https://github.com/adityaramesh/concurrency_runtime/tree/master/VS2013_SP2/crt/src/thr) (`cthread.c`) and its `atomic.c`, [microsoft/STL `cthread.cpp`](https://github.com/microsoft/STL/blob/main/stl/src/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](../../../core/libs/prx/libSceAmpr/Export.cpp) (libSceAmpr) - take a pointer to the handle slot like the libc `_Cnd_*` exports from [#3079](https://github.com/boykopovar/AnyPS5/pull/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`](https://github.com/red-prig/fpPS4/blob/trunk/src/libcinternal/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](../../../core/libs/prx/libSceAmpr/Export.cpp) (libSceAmpr) follows Dinkumware V6.00 `thr/xthread` and `thr/threadcall.cpp` of Visual C++ 2013 ([crt.vc12 `f1d47126`](https://github.com/ganboing/crt.vc12/tree/f1d47126/src/thr)), 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