rpcs3/rpcs3/Emu/Cell/lv2/lv2.cpp
2023-02-15 08:58:02 +01:00

1930 lines
81 KiB
C++

#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Memory/vm_ptr.h"
#include "Emu/Memory/vm_locking.h"
#include "Emu/Cell/PPUFunction.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/MFC.h"
#include "sys_sync.h"
#include "sys_lwmutex.h"
#include "sys_lwcond.h"
#include "sys_mutex.h"
#include "sys_cond.h"
#include "sys_event.h"
#include "sys_event_flag.h"
#include "sys_game.h"
#include "sys_interrupt.h"
#include "sys_memory.h"
#include "sys_mmapper.h"
#include "sys_net.h"
#include "sys_overlay.h"
#include "sys_ppu_thread.h"
#include "sys_process.h"
#include "sys_prx.h"
#include "sys_rsx.h"
#include "sys_rwlock.h"
#include "sys_semaphore.h"
#include "sys_spu.h"
#include "sys_time.h"
#include "sys_timer.h"
#include "sys_trace.h"
#include "sys_tty.h"
#include "sys_usbd.h"
#include "sys_vm.h"
#include "sys_fs.h"
#include "sys_dbg.h"
#include "sys_gamepad.h"
#include "sys_ss.h"
#include "sys_gpio.h"
#include "sys_config.h"
#include "sys_bdemu.h"
#include "sys_btsetting.h"
#include "sys_console.h"
#include "sys_hid.h"
#include "sys_io.h"
#include "sys_rsxaudio.h"
#include "sys_sm.h"
#include "sys_storage.h"
#include "sys_uart.h"
#include "sys_crypto_engine.h"
#include <optional>
#include <deque>
#include "util/tsc.hpp"
extern std::string ppu_get_syscall_name(u64 code);
namespace rsx
{
void set_rsx_yield_flag() noexcept;
}
template <>
void fmt_class_string<ppu_syscall_code>::format(std::string& out, u64 arg)
{
out += ppu_get_syscall_name(arg);
}
template <>
void fmt_class_string<lv2_protocol>::format(std::string& out, u64 arg)
{
format_enum(out, arg, [](auto value)
{
switch (value)
{
case SYS_SYNC_FIFO: return "FIFO";
case SYS_SYNC_PRIORITY: return "PRIO";
case SYS_SYNC_PRIORITY_INHERIT: return "PRIO-INHER";
case SYS_SYNC_RETRY: return "RETRY";
}
return unknown;
});
}
static void null_func_(ppu_thread& ppu, ppu_opcode_t, be_t<u32>* this_op, ppu_intrp_func*)
{
ppu_log.todo("Unimplemented syscall %s -> CELL_OK (r3=0x%llx, r4=0x%llx, r5=0x%llx, r6=0x%llx, r7=0x%llx, r8=0x%llx, r9=0x%llx, r10=0x%llx)", ppu_syscall_code(ppu.gpr[11]),
ppu.gpr[3], ppu.gpr[4], ppu.gpr[5], ppu.gpr[6], ppu.gpr[7], ppu.gpr[8], ppu.gpr[9], ppu.gpr[10]);
ppu.gpr[3] = 0;
ppu.cia = vm::get_addr(this_op) + 4;
}
static void uns_func_(ppu_thread& ppu, ppu_opcode_t, be_t<u32>* this_op, ppu_intrp_func*)
{
ppu_log.trace("Unused syscall %d -> ENOSYS", ppu.gpr[11]);
ppu.gpr[3] = CELL_ENOSYS;
ppu.cia = vm::get_addr(this_op) + 4;
}
// Bind Syscall
#define BIND_SYSC(func) {BIND_FUNC(func), #func}
#define NULL_FUNC(name) {null_func_, #name}
constexpr std::pair<ppu_intrp_func_t, std::string_view> null_func{null_func_, ""};
constexpr std::pair<ppu_intrp_func_t, std::string_view> uns_func{uns_func_, ""};
// UNS = Unused
// ROOT = Root
// DBG = Debug
// DEX..DECR = Unavailable on retail consoles
// PM = Product Mode
// AuthID = Authentication ID
const std::array<std::pair<ppu_intrp_func_t, std::string_view>, 1024> g_ppu_syscall_table
{
null_func,
BIND_SYSC(sys_process_getpid), //1 (0x001)
BIND_SYSC(sys_process_wait_for_child), //2 (0x002) ROOT
BIND_SYSC(sys_process_exit3), //3 (0x003)
BIND_SYSC(sys_process_get_status), //4 (0x004) DBG
BIND_SYSC(sys_process_detach_child), //5 (0x005) DBG
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //6-11 UNS
BIND_SYSC(sys_process_get_number_of_object), //12 (0x00C)
BIND_SYSC(sys_process_get_id), //13 (0x00D)
BIND_SYSC(sys_process_is_spu_lock_line_reservation_address), //14 (0x00E)
uns_func, uns_func, uns_func, //15-17 UNS
BIND_SYSC(sys_process_getppid), //18 (0x012)
BIND_SYSC(sys_process_kill), //19 (0x013)
uns_func, //20 (0x014) UNS
NULL_FUNC(_sys_process_spawn), //21 (0x015) DBG
BIND_SYSC(_sys_process_exit), //22 (0x016)
BIND_SYSC(sys_process_wait_for_child2), //23 (0x017) DBG
null_func,//BIND_SYSC(), //24 (0x018) DBG
BIND_SYSC(sys_process_get_sdk_version), //25 (0x019)
BIND_SYSC(_sys_process_exit2), //26 (0x01A)
BIND_SYSC(sys_process_spawns_a_self2), //27 (0x01B) DBG
NULL_FUNC(_sys_process_get_number_of_object), //28 (0x01C) ROOT
BIND_SYSC(sys_process_get_id2), //29 (0x01D) ROOT
BIND_SYSC(_sys_process_get_paramsfo), //30 (0x01E)
NULL_FUNC(sys_process_get_ppu_guid), //31 (0x01F)
uns_func, uns_func ,uns_func , uns_func ,uns_func, uns_func ,uns_func, uns_func ,uns_func, //32-40 UNS
BIND_SYSC(_sys_ppu_thread_exit), //41 (0x029)
uns_func, //42 (0x02A) UNS
BIND_SYSC(sys_ppu_thread_yield), //43 (0x02B)
BIND_SYSC(sys_ppu_thread_join), //44 (0x02C)
BIND_SYSC(sys_ppu_thread_detach), //45 (0x02D)
BIND_SYSC(sys_ppu_thread_get_join_state), //46 (0x02E)
BIND_SYSC(sys_ppu_thread_set_priority), //47 (0x02F) DBG
BIND_SYSC(sys_ppu_thread_get_priority), //48 (0x030)
BIND_SYSC(sys_ppu_thread_get_stack_information), //49 (0x031)
BIND_SYSC(sys_ppu_thread_stop), //50 (0x032) ROOT
BIND_SYSC(sys_ppu_thread_restart), //51 (0x033) ROOT
BIND_SYSC(_sys_ppu_thread_create), //52 (0x034) DBG
BIND_SYSC(sys_ppu_thread_start), //53 (0x035)
null_func,//BIND_SYSC(sys_ppu_...), //54 (0x036) ROOT
null_func,//BIND_SYSC(sys_ppu_...), //55 (0x037) ROOT
BIND_SYSC(sys_ppu_thread_rename), //56 (0x038)
BIND_SYSC(sys_ppu_thread_recover_page_fault), //57 (0x039)
BIND_SYSC(sys_ppu_thread_get_page_fault_context), //58 (0x03A)
uns_func, //59 (0x03B) UNS
BIND_SYSC(sys_trace_create), //60 (0x03C)
BIND_SYSC(sys_trace_start), //61 (0x03D)
BIND_SYSC(sys_trace_stop), //62 (0x03E)
BIND_SYSC(sys_trace_update_top_index), //63 (0x03F)
BIND_SYSC(sys_trace_destroy), //64 (0x040)
BIND_SYSC(sys_trace_drain), //65 (0x041)
BIND_SYSC(sys_trace_attach_process), //66 (0x042)
BIND_SYSC(sys_trace_allocate_buffer), //67 (0x043)
BIND_SYSC(sys_trace_free_buffer), //68 (0x044)
BIND_SYSC(sys_trace_create2), //69 (0x045)
BIND_SYSC(sys_timer_create), //70 (0x046)
BIND_SYSC(sys_timer_destroy), //71 (0x047)
BIND_SYSC(sys_timer_get_information), //72 (0x048)
BIND_SYSC(_sys_timer_start), //73 (0x049)
BIND_SYSC(sys_timer_stop), //74 (0x04A)
BIND_SYSC(sys_timer_connect_event_queue), //75 (0x04B)
BIND_SYSC(sys_timer_disconnect_event_queue), //76 (0x04C)
NULL_FUNC(sys_trace_create2_in_cbepm), //77 (0x04D)
null_func,//BIND_SYSC(sys_trace_...), //78 (0x04E)
uns_func, //79 (0x04F) UNS
NULL_FUNC(sys_interrupt_tag_create), //80 (0x050)
BIND_SYSC(sys_interrupt_tag_destroy), //81 (0x051)
BIND_SYSC(sys_event_flag_create), //82 (0x052)
BIND_SYSC(sys_event_flag_destroy), //83 (0x053)
BIND_SYSC(_sys_interrupt_thread_establish), //84 (0x054)
BIND_SYSC(sys_event_flag_wait), //85 (0x055)
BIND_SYSC(sys_event_flag_trywait), //86 (0x056)
BIND_SYSC(sys_event_flag_set), //87 (0x057)
BIND_SYSC(sys_interrupt_thread_eoi), //88 (0x058)
BIND_SYSC(_sys_interrupt_thread_disestablish), //89 (0x059)
BIND_SYSC(sys_semaphore_create), //90 (0x05A)
BIND_SYSC(sys_semaphore_destroy), //91 (0x05B)
BIND_SYSC(sys_semaphore_wait), //92 (0x05C)
BIND_SYSC(sys_semaphore_trywait), //93 (0x05D)
BIND_SYSC(sys_semaphore_post), //94 (0x05E)
BIND_SYSC(_sys_lwmutex_create), //95 (0x05F)
BIND_SYSC(_sys_lwmutex_destroy), //96 (0x060)
BIND_SYSC(_sys_lwmutex_lock), //97 (0x061)
BIND_SYSC(_sys_lwmutex_unlock), //98 (0x062)
BIND_SYSC(_sys_lwmutex_trylock), //99 (0x063)
BIND_SYSC(sys_mutex_create), //100 (0x064)
BIND_SYSC(sys_mutex_destroy), //101 (0x065)
BIND_SYSC(sys_mutex_lock), //102 (0x066)
BIND_SYSC(sys_mutex_trylock), //103 (0x067)
BIND_SYSC(sys_mutex_unlock), //104 (0x068)
BIND_SYSC(sys_cond_create), //105 (0x069)
BIND_SYSC(sys_cond_destroy), //106 (0x06A)
BIND_SYSC(sys_cond_wait), //107 (0x06B)
BIND_SYSC(sys_cond_signal), //108 (0x06C)
BIND_SYSC(sys_cond_signal_all), //109 (0x06D)
BIND_SYSC(sys_cond_signal_to), //110 (0x06E)
BIND_SYSC(_sys_lwcond_create), //111 (0x06F)
BIND_SYSC(_sys_lwcond_destroy), //112 (0x070)
BIND_SYSC(_sys_lwcond_queue_wait), //113 (0x071)
BIND_SYSC(sys_semaphore_get_value), //114 (0x072)
BIND_SYSC(_sys_lwcond_signal), //115 (0x073)
BIND_SYSC(_sys_lwcond_signal_all), //116 (0x074)
BIND_SYSC(_sys_lwmutex_unlock2), //117 (0x075)
BIND_SYSC(sys_event_flag_clear), //118 (0x076)
BIND_SYSC(sys_time_get_rtc), //119 (0x077) ROOT
BIND_SYSC(sys_rwlock_create), //120 (0x078)
BIND_SYSC(sys_rwlock_destroy), //121 (0x079)
BIND_SYSC(sys_rwlock_rlock), //122 (0x07A)
BIND_SYSC(sys_rwlock_tryrlock), //123 (0x07B)
BIND_SYSC(sys_rwlock_runlock), //124 (0x07C)
BIND_SYSC(sys_rwlock_wlock), //125 (0x07D)
BIND_SYSC(sys_rwlock_trywlock), //126 (0x07E)
BIND_SYSC(sys_rwlock_wunlock), //127 (0x07F)
BIND_SYSC(sys_event_queue_create), //128 (0x080)
BIND_SYSC(sys_event_queue_destroy), //129 (0x081)
BIND_SYSC(sys_event_queue_receive), //130 (0x082)
BIND_SYSC(sys_event_queue_tryreceive), //131 (0x083)
BIND_SYSC(sys_event_flag_cancel), //132 (0x084)
BIND_SYSC(sys_event_queue_drain), //133 (0x085)
BIND_SYSC(sys_event_port_create), //134 (0x086)
BIND_SYSC(sys_event_port_destroy), //135 (0x087)
BIND_SYSC(sys_event_port_connect_local), //136 (0x088)
BIND_SYSC(sys_event_port_disconnect), //137 (0x089)
BIND_SYSC(sys_event_port_send), //138 (0x08A)
BIND_SYSC(sys_event_flag_get), //139 (0x08B)
BIND_SYSC(sys_event_port_connect_ipc), //140 (0x08C)
BIND_SYSC(sys_timer_usleep), //141 (0x08D)
BIND_SYSC(sys_timer_sleep), //142 (0x08E)
NULL_FUNC(sys_time_set_timezone), //143 (0x08F) ROOT
BIND_SYSC(sys_time_get_timezone), //144 (0x090)
BIND_SYSC(sys_time_get_current_time), //145 (0x091)
NULL_FUNC(sys_time_get_system_time), //146 (0x092) ROOT
BIND_SYSC(sys_time_get_timebase_frequency), //147 (0x093)
BIND_SYSC(_sys_rwlock_trywlock), //148 (0x094)
uns_func, //149 (0x095) UNS
BIND_SYSC(sys_raw_spu_create_interrupt_tag), //150 (0x096)
BIND_SYSC(sys_raw_spu_set_int_mask), //151 (0x097)
BIND_SYSC(sys_raw_spu_get_int_mask), //152 (0x098)
BIND_SYSC(sys_raw_spu_set_int_stat), //153 (0x099)
BIND_SYSC(sys_raw_spu_get_int_stat), //154 (0x09A)
BIND_SYSC(_sys_spu_image_get_information), //155 (0x09B)
BIND_SYSC(sys_spu_image_open), //156 (0x09C)
BIND_SYSC(_sys_spu_image_import), //157 (0x09D)
BIND_SYSC(_sys_spu_image_close), //158 (0x09E)
BIND_SYSC(_sys_spu_image_get_segments), //159 (0x09F)
BIND_SYSC(sys_raw_spu_create), //160 (0x0A0)
BIND_SYSC(sys_raw_spu_destroy), //161 (0x0A1)
uns_func, //162 (0x0A2) UNS
BIND_SYSC(sys_raw_spu_read_puint_mb), //163 (0x0A3)
uns_func, //164 (0x0A4) UNS
BIND_SYSC(sys_spu_thread_get_exit_status), //165 (0x0A5)
BIND_SYSC(sys_spu_thread_set_argument), //166 (0x0A6)
NULL_FUNC(sys_spu_thread_group_start_on_exit), //167 (0x0A7)
uns_func, //168 (0x0A8) UNS
BIND_SYSC(sys_spu_initialize), //169 (0x0A9)
BIND_SYSC(sys_spu_thread_group_create), //170 (0x0AA)
BIND_SYSC(sys_spu_thread_group_destroy), //171 (0x0AB)
BIND_SYSC(sys_spu_thread_initialize), //172 (0x0AC)
BIND_SYSC(sys_spu_thread_group_start), //173 (0x0AD)
BIND_SYSC(sys_spu_thread_group_suspend), //174 (0x0AE)
BIND_SYSC(sys_spu_thread_group_resume), //175 (0x0AF)
BIND_SYSC(sys_spu_thread_group_yield), //176 (0x0B0)
BIND_SYSC(sys_spu_thread_group_terminate), //177 (0x0B1)
BIND_SYSC(sys_spu_thread_group_join), //178 (0x0B2)
BIND_SYSC(sys_spu_thread_group_set_priority), //179 (0x0B3)
BIND_SYSC(sys_spu_thread_group_get_priority), //180 (0x0B4)
BIND_SYSC(sys_spu_thread_write_ls), //181 (0x0B5)
BIND_SYSC(sys_spu_thread_read_ls), //182 (0x0B6)
uns_func, //183 (0x0B7) UNS
BIND_SYSC(sys_spu_thread_write_snr), //184 (0x0B8)
BIND_SYSC(sys_spu_thread_group_connect_event), //185 (0x0B9)
BIND_SYSC(sys_spu_thread_group_disconnect_event), //186 (0x0BA)
BIND_SYSC(sys_spu_thread_set_spu_cfg), //187 (0x0BB)
BIND_SYSC(sys_spu_thread_get_spu_cfg), //188 (0x0BC)
uns_func, //189 (0x0BD) UNS
BIND_SYSC(sys_spu_thread_write_spu_mb), //190 (0x0BE)
BIND_SYSC(sys_spu_thread_connect_event), //191 (0x0BF)
BIND_SYSC(sys_spu_thread_disconnect_event), //192 (0x0C0)
BIND_SYSC(sys_spu_thread_bind_queue), //193 (0x0C1)
BIND_SYSC(sys_spu_thread_unbind_queue), //194 (0x0C2)
uns_func, //195 (0x0C3) UNS
BIND_SYSC(sys_raw_spu_set_spu_cfg), //196 (0x0C4)
BIND_SYSC(sys_raw_spu_get_spu_cfg), //197 (0x0C5)
BIND_SYSC(sys_spu_thread_recover_page_fault), //198 (0x0C6)
BIND_SYSC(sys_raw_spu_recover_page_fault), //199 (0x0C7)
null_func, null_func, null_func, null_func, null_func, //204 UNS?
null_func, null_func, null_func, null_func, null_func, //209 UNS?
null_func, null_func, null_func, //212 UNS?
BIND_SYSC(sys_console_write2), //213 (0x0D5)
null_func, //214 UNS?
NULL_FUNC(sys_dbg_mat_set_condition), //215 (0x0D7)
NULL_FUNC(sys_dbg_mat_get_condition), //216 (0x0D8)
uns_func,//BIND_SYSC(sys_dbg_...), //217 (0x0D9) DBG UNS?
uns_func,//BIND_SYSC(sys_dbg_...), //218 (0x0DA) DBG UNS?
uns_func,//BIND_SYSC(sys_dbg_...), //219 (0x0DB) DBG UNS?
null_func, null_func, null_func, null_func, null_func, //224 UNS
null_func, null_func, null_func, null_func, null_func, //229 UNS?
BIND_SYSC(sys_isolated_spu_create), //230 (0x0E6) ROOT
BIND_SYSC(sys_isolated_spu_destroy), //231 (0x0E7) ROOT
BIND_SYSC(sys_isolated_spu_start), //232 (0x0E8) ROOT
BIND_SYSC(sys_isolated_spu_create_interrupt_tag), //233 (0x0E9) ROOT
BIND_SYSC(sys_isolated_spu_set_int_mask), //234 (0x0EA) ROOT
BIND_SYSC(sys_isolated_spu_get_int_mask), //235 (0x0EB) ROOT
BIND_SYSC(sys_isolated_spu_set_int_stat), //236 (0x0EC) ROOT
BIND_SYSC(sys_isolated_spu_get_int_stat), //237 (0x0ED) ROOT
BIND_SYSC(sys_isolated_spu_set_spu_cfg), //238 (0x0EE) ROOT
BIND_SYSC(sys_isolated_spu_get_spu_cfg), //239 (0x0EF) ROOT
BIND_SYSC(sys_isolated_spu_read_puint_mb), //240 (0x0F0) ROOT
uns_func, uns_func, uns_func, //241-243 ROOT UNS
NULL_FUNC(sys_spu_thread_group_system_set_next_group), //244 (0x0F4) ROOT
NULL_FUNC(sys_spu_thread_group_system_unset_next_group),//245 (0x0F5) ROOT
NULL_FUNC(sys_spu_thread_group_system_set_switch_group),//246 (0x0F6) ROOT
NULL_FUNC(sys_spu_thread_group_system_unset_switch_group),//247 (0x0F7) ROOT
null_func,//BIND_SYSC(sys_spu_thread_group...), //248 (0x0F8) ROOT
null_func,//BIND_SYSC(sys_spu_thread_group...), //249 (0x0F9) ROOT
BIND_SYSC(sys_spu_thread_group_set_cooperative_victims),//250 (0x0FA)
BIND_SYSC(sys_spu_thread_group_connect_event_all_threads), //251 (0x0FB)
BIND_SYSC(sys_spu_thread_group_disconnect_event_all_threads), //252 (0x0FC)
BIND_SYSC(sys_spu_thread_group_syscall_253), //253 (0x0FD)
BIND_SYSC(sys_spu_thread_group_log), //254 (0x0FE)
uns_func, uns_func, uns_func, uns_func, uns_func, //255-259 UNS
NULL_FUNC(sys_spu_image_open_by_fd), //260 (0x104)
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //261-269 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //270-279 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //280-289 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //290-299 UNS
BIND_SYSC(sys_vm_memory_map), //300 (0x12C)
BIND_SYSC(sys_vm_unmap), //301 (0x12D)
BIND_SYSC(sys_vm_append_memory), //302 (0x12E)
BIND_SYSC(sys_vm_return_memory), //303 (0x12F)
BIND_SYSC(sys_vm_lock), //304 (0x130)
BIND_SYSC(sys_vm_unlock), //305 (0x131)
BIND_SYSC(sys_vm_touch), //306 (0x132)
BIND_SYSC(sys_vm_flush), //307 (0x133)
BIND_SYSC(sys_vm_invalidate), //308 (0x134)
BIND_SYSC(sys_vm_store), //309 (0x135)
BIND_SYSC(sys_vm_sync), //310 (0x136)
BIND_SYSC(sys_vm_test), //311 (0x137)
BIND_SYSC(sys_vm_get_statistics), //312 (0x138)
BIND_SYSC(sys_vm_memory_map_different), //313 (0x139)
null_func,//BIND_SYSC(sys_...), //314 (0x13A)
null_func,//BIND_SYSC(sys_...), //315 (0x13B)
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //316-323 UNS
BIND_SYSC(sys_memory_container_create), //324 (0x144) DBG
BIND_SYSC(sys_memory_container_destroy), //325 (0x145) DBG
BIND_SYSC(sys_mmapper_allocate_fixed_address), //326 (0x146)
BIND_SYSC(sys_mmapper_enable_page_fault_notification), //327 (0x147)
BIND_SYSC(sys_mmapper_allocate_shared_memory_from_container_ext), //328 (0x148)
BIND_SYSC(sys_mmapper_free_shared_memory), //329 (0x149)
BIND_SYSC(sys_mmapper_allocate_address), //330 (0x14A)
BIND_SYSC(sys_mmapper_free_address), //331 (0x14B)
BIND_SYSC(sys_mmapper_allocate_shared_memory), //332 (0x14C)
NULL_FUNC(sys_mmapper_set_shared_memory_flag), //333(0x14D)
BIND_SYSC(sys_mmapper_map_shared_memory), //334 (0x14E)
BIND_SYSC(sys_mmapper_unmap_shared_memory), //335 (0x14F)
BIND_SYSC(sys_mmapper_change_address_access_right), //336 (0x150)
BIND_SYSC(sys_mmapper_search_and_map), //337 (0x151)
NULL_FUNC(sys_mmapper_get_shared_memory_attribute), //338 (0x152)
BIND_SYSC(sys_mmapper_allocate_shared_memory_ext), //339 (0x153)
null_func,//BIND_SYSC(sys_...), //340 (0x154)
BIND_SYSC(sys_memory_container_create), //341 (0x155)
BIND_SYSC(sys_memory_container_destroy), //342 (0x156)
BIND_SYSC(sys_memory_container_get_size), //343 (0x157)
NULL_FUNC(sys_memory_budget_set), //344 (0x158)
BIND_SYSC(sys_memory_container_destroy_parent_with_childs), //345 (0x159)
null_func,//BIND_SYSC(sys_memory_...), //346 (0x15A)
uns_func, //347 (0x15B) UNS
BIND_SYSC(sys_memory_allocate), //348 (0x15C)
BIND_SYSC(sys_memory_free), //349 (0x15D)
BIND_SYSC(sys_memory_allocate_from_container), //350 (0x15E)
BIND_SYSC(sys_memory_get_page_attribute), //351 (0x15F)
BIND_SYSC(sys_memory_get_user_memory_size), //352 (0x160)
BIND_SYSC(sys_memory_get_user_memory_stat), //353 (0x161)
null_func,//BIND_SYSC(sys_memory_...), //354 (0x162)
null_func,//BIND_SYSC(sys_memory_...), //355 (0x163)
NULL_FUNC(sys_memory_allocate_colored), //356 (0x164)
null_func,//BIND_SYSC(sys_memory_...), //357 (0x165)
null_func,//BIND_SYSC(sys_memory_...), //358 (0x166)
null_func,//BIND_SYSC(sys_memory_...), //359 (0x167)
null_func,//BIND_SYSC(sys_memory_...), //360 (0x168)
NULL_FUNC(sys_memory_allocate_from_container_colored), //361 (0x169)
BIND_SYSC(sys_mmapper_allocate_shared_memory_from_container),//362 (0x16A)
null_func,//BIND_SYSC(sys_mmapper_...), //363 (0x16B)
null_func,//BIND_SYSC(sys_mmapper_...), //364 (0x16C)
uns_func, uns_func, //366 (0x16E) UNS
BIND_SYSC(sys_uart_initialize), //367 (0x16F) ROOT
BIND_SYSC(sys_uart_receive), //368 (0x170) ROOT
BIND_SYSC(sys_uart_send), //369 (0x171) ROOT
BIND_SYSC(sys_uart_get_params), //370 (0x172) ROOT
uns_func, //371 (0x173) UNS
BIND_SYSC(_sys_game_watchdog_start), //372 (0x174)
BIND_SYSC(_sys_game_watchdog_stop), //373 (0x175)
BIND_SYSC(_sys_game_watchdog_clear), //374 (0x176)
NULL_FUNC(sys_game_set_system_sw_version), //375 (0x177) ROOT
BIND_SYSC(_sys_game_get_system_sw_version), //376 (0x178) ROOT
BIND_SYSC(sys_sm_set_shop_mode), //377 (0x179) ROOT
BIND_SYSC(sys_sm_get_ext_event2), //378 (0x17A) ROOT
BIND_SYSC(sys_sm_shutdown), //379 (0x17B) ROOT
BIND_SYSC(sys_sm_get_params), //380 (0x17C) DBG
NULL_FUNC(sys_sm_get_inter_lpar_parameter), //381 (0x17D) ROOT
NULL_FUNC(sys_sm_initialize), //382 (0x17E) ROOT
NULL_FUNC(sys_game_get_temperature), //383 (0x17F) ROOT
NULL_FUNC(sys_sm_get_tzpb), //384 (0x180) ROOT
NULL_FUNC(sys_sm_request_led), //385 (0x181) ROOT
BIND_SYSC(sys_sm_control_led), //386 (0x182) ROOT
NULL_FUNC(sys_sm_get_system_info), //387 (0x183) DBG
BIND_SYSC(sys_sm_ring_buzzer2), //388 (0x184) ROOT
NULL_FUNC(sys_sm_set_fan_policy), //389 (0x185) PM
NULL_FUNC(sys_sm_request_error_log), //390 (0x186) ROOT
NULL_FUNC(sys_sm_request_be_count), //391 (0x187) ROOT
BIND_SYSC(sys_sm_ring_buzzer), //392 (0x188) ROOT
NULL_FUNC(sys_sm_get_hw_config), //393 (0x189) ROOT
NULL_FUNC(sys_sm_request_scversion), //394 (0x18A) ROOT
NULL_FUNC(sys_sm_request_system_event_log), //395 (0x18B) PM
NULL_FUNC(sys_sm_set_rtc_alarm), //396 (0x18C) ROOT
NULL_FUNC(sys_sm_get_rtc_alarm), //397 (0x18D) ROOT
BIND_SYSC(sys_console_write), //398 (0x18E) ROOT
uns_func, //399 (0x18F) UNS
null_func,//BIND_SYSC(sys_sm_...), //400 (0x190) PM
null_func,//BIND_SYSC(sys_sm_...), //401 (0x191) ROOT
BIND_SYSC(sys_tty_read), //402 (0x192)
BIND_SYSC(sys_tty_write), //403 (0x193)
null_func,//BIND_SYSC(sys_...), //404 (0x194) ROOT
null_func,//BIND_SYSC(sys_...), //405 (0x195) PM
null_func,//BIND_SYSC(sys_...), //406 (0x196) PM
null_func,//BIND_SYSC(sys_...), //407 (0x197) PM
NULL_FUNC(sys_sm_get_tzpb), //408 (0x198) PM
NULL_FUNC(sys_sm_get_fan_policy), //409 (0x199) PM
BIND_SYSC(_sys_game_board_storage_read), //410 (0x19A)
BIND_SYSC(_sys_game_board_storage_write), //411 (0x19B)
BIND_SYSC(_sys_game_get_rtc_status), //412 (0x19C)
null_func,//BIND_SYSC(sys_...), //413 (0x19D) ROOT
null_func,//BIND_SYSC(sys_...), //414 (0x19E) ROOT
null_func,//BIND_SYSC(sys_...), //415 (0x19F) ROOT
uns_func, uns_func, uns_func, uns_func, //416-419 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //420-429 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //430-439 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //440-449 UNS
BIND_SYSC(sys_overlay_load_module), //450 (0x1C2)
BIND_SYSC(sys_overlay_unload_module), //451 (0x1C3)
NULL_FUNC(sys_overlay_get_module_list), //452 (0x1C4)
NULL_FUNC(sys_overlay_get_module_info), //453 (0x1C5)
BIND_SYSC(sys_overlay_load_module_by_fd), //454 (0x1C6)
NULL_FUNC(sys_overlay_get_module_info2), //455 (0x1C7)
NULL_FUNC(sys_overlay_get_sdk_version), //456 (0x1C8)
NULL_FUNC(sys_overlay_get_module_dbg_info), //457 (0x1C9)
NULL_FUNC(sys_overlay_get_module_dbg_info), //458 (0x1CA)
uns_func, //459 (0x1CB) UNS
NULL_FUNC(sys_prx_dbg_get_module_id_list), //460 (0x1CC) ROOT
BIND_SYSC(_sys_prx_get_module_id_by_address), //461 (0x1CD)
uns_func, //462 (0x1CE) DEX
BIND_SYSC(_sys_prx_load_module_by_fd), //463 (0x1CF)
BIND_SYSC(_sys_prx_load_module_on_memcontainer_by_fd), //464 (0x1D0)
BIND_SYSC(_sys_prx_load_module_list), //465 (0x1D1)
BIND_SYSC(_sys_prx_load_module_list_on_memcontainer), //466 (0x1D2)
BIND_SYSC(sys_prx_get_ppu_guid), //467 (0x1D3)
null_func,//BIND_SYSC(sys_...), //468 (0x1D4) ROOT
uns_func, //469 (0x1D5) UNS
NULL_FUNC(sys_npdrm_check_ekc), //470 (0x1D6) ROOT
NULL_FUNC(sys_npdrm_regist_ekc), //471 (0x1D7) ROOT
null_func,//BIND_SYSC(sys_...), //472 (0x1D8) ROOT
null_func,//BIND_SYSC(sys_...), //473 (0x1D9)
null_func,//BIND_SYSC(sys_...), //474 (0x1DA)
null_func,//BIND_SYSC(sys_...), //475 (0x1DB) ROOT
null_func,//BIND_SYSC(sys_...), //476 (0x1DC) ROOT
uns_func, uns_func, uns_func, //477-479 UNS
BIND_SYSC(_sys_prx_load_module), //480 (0x1E0)
BIND_SYSC(_sys_prx_start_module), //481 (0x1E1)
BIND_SYSC(_sys_prx_stop_module), //482 (0x1E2)
BIND_SYSC(_sys_prx_unload_module), //483 (0x1E3)
BIND_SYSC(_sys_prx_register_module), //484 (0x1E4)
BIND_SYSC(_sys_prx_query_module), //485 (0x1E5)
BIND_SYSC(_sys_prx_register_library), //486 (0x1E6)
BIND_SYSC(_sys_prx_unregister_library), //487 (0x1E7)
BIND_SYSC(_sys_prx_link_library), //488 (0x1E8)
BIND_SYSC(_sys_prx_unlink_library), //489 (0x1E9)
BIND_SYSC(_sys_prx_query_library), //490 (0x1EA)
uns_func, //491 (0x1EB) UNS
NULL_FUNC(sys_prx_dbg_get_module_list), //492 (0x1EC) DBG
NULL_FUNC(sys_prx_dbg_get_module_info), //493 (0x1ED) DBG
BIND_SYSC(_sys_prx_get_module_list), //494 (0x1EE)
BIND_SYSC(_sys_prx_get_module_info), //495 (0x1EF)
BIND_SYSC(_sys_prx_get_module_id_by_name), //496 (0x1F0)
BIND_SYSC(_sys_prx_load_module_on_memcontainer), //497 (0x1F1)
BIND_SYSC(_sys_prx_start), //498 (0x1F2)
BIND_SYSC(_sys_prx_stop), //499 (0x1F3)
BIND_SYSC(sys_hid_manager_open), //500 (0x1F4)
NULL_FUNC(sys_hid_manager_close), //501 (0x1F5)
BIND_SYSC(sys_hid_manager_read), //502 (0x1F6) ROOT
BIND_SYSC(sys_hid_manager_ioctl), //503 (0x1F7)
NULL_FUNC(sys_hid_manager_map_logical_id_to_port_id), //504 (0x1F8) ROOT
NULL_FUNC(sys_hid_manager_unmap_logical_id_to_port_id), //505 (0x1F9) ROOT
BIND_SYSC(sys_hid_manager_add_hot_key_observer), //506 (0x1FA) ROOT
NULL_FUNC(sys_hid_manager_remove_hot_key_observer), //507 (0x1FB) ROOT
NULL_FUNC(sys_hid_manager_grab_focus), //508 (0x1FC) ROOT
NULL_FUNC(sys_hid_manager_release_focus), //509 (0x1FD) ROOT
BIND_SYSC(sys_hid_manager_check_focus), //510 (0x1FE)
NULL_FUNC(sys_hid_manager_set_master_process), //511 (0x1FF) ROOT
BIND_SYSC(sys_hid_manager_is_process_permission_root), //512 (0x200) ROOT
BIND_SYSC(sys_hid_manager_513), //513 (0x201)
BIND_SYSC(sys_hid_manager_514), //514 (0x202)
uns_func, //515 (0x203) UNS
BIND_SYSC(sys_config_open), //516 (0x204)
BIND_SYSC(sys_config_close), //517 (0x205)
BIND_SYSC(sys_config_get_service_event), //518 (0x206)
BIND_SYSC(sys_config_add_service_listener), //519 (0x207)
BIND_SYSC(sys_config_remove_service_listener), //520 (0x208)
BIND_SYSC(sys_config_register_service), //521 (0x209)
BIND_SYSC(sys_config_unregister_service), //522 (0x20A)
BIND_SYSC(sys_config_get_io_event), //523 (0x20B)
BIND_SYSC(sys_config_register_io_error_listener), //524 (0x20C)
BIND_SYSC(sys_config_unregister_io_error_listener), //525 (0x20D)
uns_func, uns_func, uns_func, uns_func, //526-529 UNS
BIND_SYSC(sys_usbd_initialize), //530 (0x212)
BIND_SYSC(sys_usbd_finalize), //531 (0x213)
BIND_SYSC(sys_usbd_get_device_list), //532 (0x214)
BIND_SYSC(sys_usbd_get_descriptor_size), //533 (0x215)
BIND_SYSC(sys_usbd_get_descriptor), //534 (0x216)
BIND_SYSC(sys_usbd_register_ldd), //535 (0x217)
BIND_SYSC(sys_usbd_unregister_ldd), //536 (0x218)
BIND_SYSC(sys_usbd_open_pipe), //537 (0x219)
BIND_SYSC(sys_usbd_open_default_pipe), //538 (0x21A)
BIND_SYSC(sys_usbd_close_pipe), //539 (0x21B)
BIND_SYSC(sys_usbd_receive_event), //540 (0x21C)
BIND_SYSC(sys_usbd_detect_event), //541 (0x21D)
BIND_SYSC(sys_usbd_attach), //542 (0x21E)
BIND_SYSC(sys_usbd_transfer_data), //543 (0x21F)
BIND_SYSC(sys_usbd_isochronous_transfer_data), //544 (0x220)
BIND_SYSC(sys_usbd_get_transfer_status), //545 (0x221)
BIND_SYSC(sys_usbd_get_isochronous_transfer_status), //546 (0x222)
BIND_SYSC(sys_usbd_get_device_location), //547 (0x223)
BIND_SYSC(sys_usbd_send_event), //548 (0x224)
BIND_SYSC(sys_usbd_event_port_send), //549 (0x225)
BIND_SYSC(sys_usbd_allocate_memory), //550 (0x226)
BIND_SYSC(sys_usbd_free_memory), //551 (0x227)
null_func,//BIND_SYSC(sys_usbd_...), //552 (0x228)
null_func,//BIND_SYSC(sys_usbd_...), //553 (0x229)
null_func,//BIND_SYSC(sys_usbd_...), //554 (0x22A)
null_func,//BIND_SYSC(sys_usbd_...), //555 (0x22B)
BIND_SYSC(sys_usbd_get_device_speed), //556 (0x22C)
null_func,//BIND_SYSC(sys_usbd_...), //557 (0x22D)
null_func,//BIND_SYSC(sys_usbd_...), //558 (0x22E)
BIND_SYSC(sys_usbd_register_extra_ldd), //559 (0x22F)
null_func,//BIND_SYSC(sys_...), //560 (0x230) ROOT
null_func,//BIND_SYSC(sys_...), //561 (0x231) ROOT
null_func,//BIND_SYSC(sys_...), //562 (0x232) ROOT
null_func,//BIND_SYSC(sys_...), //563 (0x233)
null_func,//BIND_SYSC(sys_...), //564 (0x234)
null_func,//BIND_SYSC(sys_...), //565 (0x235)
null_func,//BIND_SYSC(sys_...), //566 (0x236)
null_func,//BIND_SYSC(sys_...), //567 (0x237)
null_func,//BIND_SYSC(sys_...), //568 (0x238)
null_func,//BIND_SYSC(sys_...), //569 (0x239)
NULL_FUNC(sys_pad_ldd_register_controller), //570 (0x23A)
NULL_FUNC(sys_pad_ldd_unregister_controller), //571 (0x23B)
NULL_FUNC(sys_pad_ldd_data_insert), //572 (0x23C)
NULL_FUNC(sys_pad_dbg_ldd_set_data_insert_mode), //573 (0x23D)
NULL_FUNC(sys_pad_ldd_register_controller), //574 (0x23E)
NULL_FUNC(sys_pad_ldd_get_port_no), //575 (0x23F)
uns_func, //576 (0x240) UNS
null_func,//BIND_SYSC(sys_pad_manager_...), //577 (0x241) ROOT PM
null_func,//BIND_SYSC(sys_bluetooth_...), //578 (0x242)
null_func,//BIND_SYSC(sys_bluetooth_aud_serial_...), //579 (0x243)
null_func,//BIND_SYSC(sys_bluetooth_...), //580 (0x244) ROOT
null_func,//BIND_SYSC(sys_bluetooth_...), //581 (0x245) ROOT
null_func,//BIND_SYSC(sys_bluetooth_...), //582 (0x246) ROOT
NULL_FUNC(sys_bt_read_firmware_version), //583 (0x247) ROOT
NULL_FUNC(sys_bt_complete_wake_on_host), //584 (0x248) ROOT
NULL_FUNC(sys_bt_disable_bluetooth), //585 (0x249)
NULL_FUNC(sys_bt_enable_bluetooth), //586 (0x24A)
NULL_FUNC(sys_bt_bccmd), //587 (0x24B) ROOT
NULL_FUNC(sys_bt_read_hq), //588 (0x24C)
NULL_FUNC(sys_bt_hid_get_remote_status), //589 (0x24D)
NULL_FUNC(sys_bt_register_controller), //590 (0x24E) ROOT
NULL_FUNC(sys_bt_clear_registered_contoller), //591 (0x24F)
NULL_FUNC(sys_bt_connect_accept_controller), //592 (0x250)
NULL_FUNC(sys_bt_get_local_bdaddress), //593 (0x251) ROOT
NULL_FUNC(sys_bt_hid_get_data), //594 (0x252)
NULL_FUNC(sys_bt_hid_set_report), //595 (0x253)
NULL_FUNC(sys_bt_sched_log), //596 (0x254)
NULL_FUNC(sys_bt_cancel_connect_accept_controller), //597 (0x255)
null_func,//BIND_SYSC(sys_bluetooth_...), //598 (0x256) ROOT
null_func,//BIND_SYSC(sys_bluetooth_...), //599 (0x257) ROOT
BIND_SYSC(sys_storage_open), //600 (0x258) ROOT
BIND_SYSC(sys_storage_close), //601 (0x259)
BIND_SYSC(sys_storage_read), //602 (0x25A)
BIND_SYSC(sys_storage_write), //603 (0x25B)
BIND_SYSC(sys_storage_send_device_command), //604 (0x25C)
BIND_SYSC(sys_storage_async_configure), //605 (0x25D)
BIND_SYSC(sys_storage_async_read), //606 (0x25E)
BIND_SYSC(sys_storage_async_write), //607 (0x25F)
BIND_SYSC(sys_storage_async_cancel), //608 (0x260)
BIND_SYSC(sys_storage_get_device_info), //609 (0x261) ROOT
BIND_SYSC(sys_storage_get_device_config), //610 (0x262) ROOT
BIND_SYSC(sys_storage_report_devices), //611 (0x263) ROOT
BIND_SYSC(sys_storage_configure_medium_event), //612 (0x264) ROOT
BIND_SYSC(sys_storage_set_medium_polling_interval), //613 (0x265)
BIND_SYSC(sys_storage_create_region), //614 (0x266)
BIND_SYSC(sys_storage_delete_region), //615 (0x267)
BIND_SYSC(sys_storage_execute_device_command), //616 (0x268)
BIND_SYSC(sys_storage_check_region_acl), //617 (0x269)
BIND_SYSC(sys_storage_set_region_acl), //618 (0x26A)
BIND_SYSC(sys_storage_async_send_device_command), //619 (0x26B)
null_func,//BIND_SYSC(sys_...), //620 (0x26C) ROOT
BIND_SYSC(sys_gamepad_ycon_if), //621 (0x26D)
BIND_SYSC(sys_storage_get_region_offset), //622 (0x26E)
BIND_SYSC(sys_storage_set_emulated_speed), //623 (0x26F)
BIND_SYSC(sys_io_buffer_create), //624 (0x270)
BIND_SYSC(sys_io_buffer_destroy), //625 (0x271)
BIND_SYSC(sys_io_buffer_allocate), //626 (0x272)
BIND_SYSC(sys_io_buffer_free), //627 (0x273)
uns_func, uns_func, //629 (0x275) UNS
BIND_SYSC(sys_gpio_set), //630 (0x276)
BIND_SYSC(sys_gpio_get), //631 (0x277)
uns_func, //632 (0x278) UNS
NULL_FUNC(sys_fsw_connect_event), //633 (0x279)
NULL_FUNC(sys_fsw_disconnect_event), //634 (0x27A)
BIND_SYSC(sys_btsetting_if), //635 (0x27B)
null_func,//BIND_SYSC(sys_...), //636 (0x27C)
null_func,//BIND_SYSC(sys_...), //637 (0x27D)
null_func,//BIND_SYSC(sys_...), //638 (0x27E)
null_func,//BIND_SYSC(sys...), //639 DEPRECATED
NULL_FUNC(sys_usbbtaudio_initialize), //640 DEPRECATED
NULL_FUNC(sys_usbbtaudio_finalize), //641 DEPRECATED
NULL_FUNC(sys_usbbtaudio_discovery), //642 DEPRECATED
NULL_FUNC(sys_usbbtaudio_cancel_discovery), //643 DEPRECATED
NULL_FUNC(sys_usbbtaudio_pairing), //644 DEPRECATED
NULL_FUNC(sys_usbbtaudio_set_passkey), //645 DEPRECATED
NULL_FUNC(sys_usbbtaudio_connect), //646 DEPRECATED
NULL_FUNC(sys_usbbtaudio_disconnect), //647 DEPRECATED
null_func,//BIND_SYSC(sys_...), //648 DEPRECATED
null_func,//BIND_SYSC(sys_...), //649 DEPRECATED
BIND_SYSC(sys_rsxaudio_initialize), //650 (0x28A)
BIND_SYSC(sys_rsxaudio_finalize), //651 (0x28B)
BIND_SYSC(sys_rsxaudio_import_shared_memory), //652 (0x28C)
BIND_SYSC(sys_rsxaudio_unimport_shared_memory), //653 (0x28D)
BIND_SYSC(sys_rsxaudio_create_connection), //654 (0x28E)
BIND_SYSC(sys_rsxaudio_close_connection), //655 (0x28F)
BIND_SYSC(sys_rsxaudio_prepare_process), //656 (0x290)
BIND_SYSC(sys_rsxaudio_start_process), //657 (0x291)
BIND_SYSC(sys_rsxaudio_stop_process), //658 (0x292)
BIND_SYSC(sys_rsxaudio_get_dma_param), //659 (0x293)
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //660-665 UNS
BIND_SYSC(sys_rsx_device_open), //666 (0x29A)
BIND_SYSC(sys_rsx_device_close), //667 (0x29B)
BIND_SYSC(sys_rsx_memory_allocate), //668 (0x29C)
BIND_SYSC(sys_rsx_memory_free), //669 (0x29D)
BIND_SYSC(sys_rsx_context_allocate), //670 (0x29E)
BIND_SYSC(sys_rsx_context_free), //671 (0x29F)
BIND_SYSC(sys_rsx_context_iomap), //672 (0x2A0)
BIND_SYSC(sys_rsx_context_iounmap), //673 (0x2A1)
BIND_SYSC(sys_rsx_context_attribute), //674 (0x2A2)
BIND_SYSC(sys_rsx_device_map), //675 (0x2A3)
BIND_SYSC(sys_rsx_device_unmap), //676 (0x2A4)
BIND_SYSC(sys_rsx_attribute), //677 (0x2A5)
null_func,//BIND_SYSC(sys_...), //678 (0x2A6)
null_func,//BIND_SYSC(sys_...), //679 (0x2A7) ROOT
null_func,//BIND_SYSC(sys_...), //680 (0x2A8) ROOT
null_func,//BIND_SYSC(sys_...), //681 (0x2A9) ROOT
null_func,//BIND_SYSC(sys_...), //682 (0x2AA) ROOT
null_func,//BIND_SYSC(sys_...), //683 (0x2AB) ROOT
null_func,//BIND_SYSC(sys_...), //684 (0x2AC) ROOT
null_func,//BIND_SYSC(sys_...), //685 (0x2AD) ROOT
null_func,//BIND_SYSC(sys_...), //686 (0x2AE) ROOT
null_func,//BIND_SYSC(sys_...), //687 (0x2AF) ROOT
null_func,//BIND_SYSC(sys_...), //688 (0x2B0) ROOT
null_func,//BIND_SYSC(sys_...), //689 (0x2B1) ROOT
null_func,//BIND_SYSC(sys_...), //690 (0x2B2) ROOT
null_func,//BIND_SYSC(sys_...), //691 (0x2B3) ROOT
null_func,//BIND_SYSC(sys_...), //692 (0x2B4) ROOT
null_func,//BIND_SYSC(sys_...), //693 (0x2B5) ROOT
null_func,//BIND_SYSC(sys_...), //694 (0x2B6) DEPRECATED
null_func,//BIND_SYSC(sys_...), //695 (0x2B7) DEPRECATED
null_func,//BIND_SYSC(sys_...), //696 (0x2B8) ROOT
uns_func,//BIND_SYSC(sys_...), //697 (0x2B9) UNS
uns_func,//BIND_SYSC(sys_...), //698 (0x2BA) UNS
BIND_SYSC(sys_bdemu_send_command), //699 (0x2BB)
BIND_SYSC(sys_net_bnet_accept), //700 (0x2BC)
BIND_SYSC(sys_net_bnet_bind), //701 (0x2BD)
BIND_SYSC(sys_net_bnet_connect), //702 (0x2BE)
BIND_SYSC(sys_net_bnet_getpeername), //703 (0x2BF)
BIND_SYSC(sys_net_bnet_getsockname), //704 (0x2C0)
BIND_SYSC(sys_net_bnet_getsockopt), //705 (0x2C1)
BIND_SYSC(sys_net_bnet_listen), //706 (0x2C2)
BIND_SYSC(sys_net_bnet_recvfrom), //707 (0x2C3)
BIND_SYSC(sys_net_bnet_recvmsg), //708 (0x2C4)
BIND_SYSC(sys_net_bnet_sendmsg), //709 (0x2C5)
BIND_SYSC(sys_net_bnet_sendto), //710 (0x2C6)
BIND_SYSC(sys_net_bnet_setsockopt), //711 (0x2C7)
BIND_SYSC(sys_net_bnet_shutdown), //712 (0x2C8)
BIND_SYSC(sys_net_bnet_socket), //713 (0x2C9)
BIND_SYSC(sys_net_bnet_close), //714 (0x2CA)
BIND_SYSC(sys_net_bnet_poll), //715 (0x2CB)
BIND_SYSC(sys_net_bnet_select), //716 (0x2CC)
BIND_SYSC(_sys_net_open_dump), //717 (0x2CD)
BIND_SYSC(_sys_net_read_dump), //718 (0x2CE)
BIND_SYSC(_sys_net_close_dump), //719 (0x2CF)
BIND_SYSC(_sys_net_write_dump), //720 (0x2D0)
BIND_SYSC(sys_net_abort), //721 (0x2D1)
BIND_SYSC(sys_net_infoctl), //722 (0x2D2)
BIND_SYSC(sys_net_control), //723 (0x2D3)
BIND_SYSC(sys_net_bnet_ioctl), //724 (0x2D4)
BIND_SYSC(sys_net_bnet_sysctl), //725 (0x2D5)
BIND_SYSC(sys_net_eurus_post_command), //726 (0x2D6)
uns_func, uns_func, uns_func, //727-729 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //730-739 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //740-749 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //750-759 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //760-769 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //770-779 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //780-789 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //790-799 UNS
BIND_SYSC(sys_fs_test), //800 (0x320)
BIND_SYSC(sys_fs_open), //801 (0x321)
BIND_SYSC(sys_fs_read), //802 (0x322)
BIND_SYSC(sys_fs_write), //803 (0x323)
BIND_SYSC(sys_fs_close), //804 (0x324)
BIND_SYSC(sys_fs_opendir), //805 (0x325)
BIND_SYSC(sys_fs_readdir), //806 (0x326)
BIND_SYSC(sys_fs_closedir), //807 (0x327)
BIND_SYSC(sys_fs_stat), //808 (0x328)
BIND_SYSC(sys_fs_fstat), //809 (0x329)
BIND_SYSC(sys_fs_link), //810 (0x32A)
BIND_SYSC(sys_fs_mkdir), //811 (0x32B)
BIND_SYSC(sys_fs_rename), //812 (0x32C)
BIND_SYSC(sys_fs_rmdir), //813 (0x32D)
BIND_SYSC(sys_fs_unlink), //814 (0x32E)
BIND_SYSC(sys_fs_utime), //815 (0x32F)
BIND_SYSC(sys_fs_access), //816 (0x330)
BIND_SYSC(sys_fs_fcntl), //817 (0x331)
BIND_SYSC(sys_fs_lseek), //818 (0x332)
BIND_SYSC(sys_fs_fdatasync), //819 (0x333)
BIND_SYSC(sys_fs_fsync), //820 (0x334)
BIND_SYSC(sys_fs_fget_block_size), //821 (0x335)
BIND_SYSC(sys_fs_get_block_size), //822 (0x336)
BIND_SYSC(sys_fs_acl_read), //823 (0x337)
BIND_SYSC(sys_fs_acl_write), //824 (0x338)
BIND_SYSC(sys_fs_lsn_get_cda_size), //825 (0x339)
BIND_SYSC(sys_fs_lsn_get_cda), //826 (0x33A)
BIND_SYSC(sys_fs_lsn_lock), //827 (0x33B)
BIND_SYSC(sys_fs_lsn_unlock), //828 (0x33C)
BIND_SYSC(sys_fs_lsn_read), //829 (0x33D)
BIND_SYSC(sys_fs_lsn_write), //830 (0x33E)
BIND_SYSC(sys_fs_truncate), //831 (0x33F)
BIND_SYSC(sys_fs_ftruncate), //832 (0x340)
BIND_SYSC(sys_fs_symbolic_link), //833 (0x341)
BIND_SYSC(sys_fs_chmod), //834 (0x342)
BIND_SYSC(sys_fs_chown), //835 (0x343)
BIND_SYSC(sys_fs_newfs), //836 (0x344)
BIND_SYSC(sys_fs_mount), //837 (0x345)
BIND_SYSC(sys_fs_unmount), //838 (0x346)
NULL_FUNC(sys_fs_sync), //839 (0x347)
BIND_SYSC(sys_fs_disk_free), //840 (0x348)
BIND_SYSC(sys_fs_get_mount_info_size), //841 (0x349)
BIND_SYSC(sys_fs_get_mount_info), //842 (0x34A)
NULL_FUNC(sys_fs_get_fs_info_size), //843 (0x34B)
NULL_FUNC(sys_fs_get_fs_info), //844 (0x34C)
BIND_SYSC(sys_fs_mapped_allocate), //845 (0x34D)
BIND_SYSC(sys_fs_mapped_free), //846 (0x34E)
BIND_SYSC(sys_fs_truncate2), //847 (0x34F)
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //848-853 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //854-859 UNS
NULL_FUNC(sys_ss_get_cache_of_analog_sunset_flag), //860 (0x35C) AUTHID
NULL_FUNC(sys_ss_protected_file_db), //861 ROOT
BIND_SYSC(sys_ss_virtual_trm_manager), //862 ROOT
BIND_SYSC(sys_ss_update_manager), //863 ROOT
NULL_FUNC(sys_ss_sec_hw_framework), //864 DBG
BIND_SYSC(sys_ss_random_number_generator), //865 (0x361)
BIND_SYSC(sys_ss_secure_rtc), //866 ROOT
BIND_SYSC(sys_ss_appliance_info_manager), //867 ROOT
BIND_SYSC(sys_ss_individual_info_manager), //868 ROOT / DBG AUTHID
NULL_FUNC(sys_ss_factory_data_manager), //869 ROOT
BIND_SYSC(sys_ss_get_console_id), //870 (0x366)
BIND_SYSC(sys_ss_access_control_engine), //871 (0x367) DBG
BIND_SYSC(sys_ss_get_open_psid), //872 (0x368)
BIND_SYSC(sys_ss_get_cache_of_product_mode), //873 (0x369)
BIND_SYSC(sys_ss_get_cache_of_flash_ext_flag), //874 (0x36A)
BIND_SYSC(sys_ss_get_boot_device), //875 (0x36B)
NULL_FUNC(sys_ss_disc_access_control), //876 (0x36C)
null_func, //BIND_SYSC(sys_ss_~utoken_if), //877 (0x36D) ROOT
NULL_FUNC(sys_ss_ad_sign), //878 (0x36E)
NULL_FUNC(sys_ss_media_id), //879 (0x36F)
NULL_FUNC(sys_deci3_open), //880 (0x370)
NULL_FUNC(sys_deci3_create_event_path), //881 (0x371)
NULL_FUNC(sys_deci3_close), //882 (0x372)
NULL_FUNC(sys_deci3_send), //883 (0x373)
NULL_FUNC(sys_deci3_receive), //884 (0x374)
NULL_FUNC(sys_deci3_open2), //885 (0x375)
uns_func, uns_func, uns_func, //886-888 UNS
null_func,//BIND_SYSC(sys_...), //889 (0x379) ROOT
NULL_FUNC(sys_deci3_initialize), //890 (0x37A)
NULL_FUNC(sys_deci3_terminate), //891 (0x37B)
NULL_FUNC(sys_deci3_debug_mode), //892 (0x37C)
NULL_FUNC(sys_deci3_show_status), //893 (0x37D)
NULL_FUNC(sys_deci3_echo_test), //894 (0x37E)
NULL_FUNC(sys_deci3_send_dcmp_packet), //895 (0x37F)
NULL_FUNC(sys_deci3_dump_cp_register), //896 (0x380)
NULL_FUNC(sys_deci3_dump_cp_buffer), //897 (0x381)
uns_func, //898 (0x382) UNS
NULL_FUNC(sys_deci3_test), //899 (0x383)
NULL_FUNC(sys_dbg_stop_processes), //900 (0x384)
NULL_FUNC(sys_dbg_continue_processes), //901 (0x385)
NULL_FUNC(sys_dbg_stop_threads), //902 (0x386)
NULL_FUNC(sys_dbg_continue_threads), //903 (0x387)
BIND_SYSC(sys_dbg_read_process_memory), //904 (0x388)
BIND_SYSC(sys_dbg_write_process_memory), //905 (0x389)
NULL_FUNC(sys_dbg_read_thread_register), //906 (0x38A)
NULL_FUNC(sys_dbg_write_thread_register), //907 (0x38B)
NULL_FUNC(sys_dbg_get_process_list), //908 (0x38C)
NULL_FUNC(sys_dbg_get_thread_list), //909 (0x38D)
NULL_FUNC(sys_dbg_get_thread_info), //910 (0x38E)
NULL_FUNC(sys_dbg_spu_thread_read_from_ls), //911 (0x38F)
NULL_FUNC(sys_dbg_spu_thread_write_to_ls), //912 (0x390)
NULL_FUNC(sys_dbg_kill_process), //913 (0x391)
NULL_FUNC(sys_dbg_get_process_info), //914 (0x392)
NULL_FUNC(sys_dbg_set_run_control_bit_to_spu), //915 (0x393)
NULL_FUNC(sys_dbg_spu_thread_get_exception_cause), //916 (0x394)
NULL_FUNC(sys_dbg_create_kernel_event_queue), //917 (0x395)
NULL_FUNC(sys_dbg_read_kernel_event_queue), //918 (0x396)
NULL_FUNC(sys_dbg_destroy_kernel_event_queue), //919 (0x397)
NULL_FUNC(sys_dbg_get_process_event_ctrl_flag), //920 (0x398)
NULL_FUNC(sys_dbg_set_process_event_cntl_flag), //921 (0x399)
NULL_FUNC(sys_dbg_get_spu_thread_group_event_cntl_flag),//922 (0x39A)
NULL_FUNC(sys_dbg_set_spu_thread_group_event_cntl_flag),//923 (0x39B)
NULL_FUNC(sys_dbg_get_module_list), //924 (0x39C)
NULL_FUNC(sys_dbg_get_raw_spu_list), //925 (0x39D)
NULL_FUNC(sys_dbg_initialize_scratch_executable_area), //926 (0x39E)
NULL_FUNC(sys_dbg_terminate_scratch_executable_area), //927 (0x3A0)
NULL_FUNC(sys_dbg_initialize_scratch_data_area), //928 (0x3A1)
NULL_FUNC(sys_dbg_terminate_scratch_data_area), //929 (0x3A2)
NULL_FUNC(sys_dbg_get_user_memory_stat), //930 (0x3A3)
NULL_FUNC(sys_dbg_get_shared_memory_attribute_list), //931 (0x3A4)
NULL_FUNC(sys_dbg_get_mutex_list), //932 (0x3A4)
NULL_FUNC(sys_dbg_get_mutex_information), //933 (0x3A5)
NULL_FUNC(sys_dbg_get_cond_list), //934 (0x3A6)
NULL_FUNC(sys_dbg_get_cond_information), //935 (0x3A7)
NULL_FUNC(sys_dbg_get_rwlock_list), //936 (0x3A8)
NULL_FUNC(sys_dbg_get_rwlock_information), //937 (0x3A9)
NULL_FUNC(sys_dbg_get_lwmutex_list), //938 (0x3AA)
NULL_FUNC(sys_dbg_get_address_from_dabr), //939 (0x3AB)
NULL_FUNC(sys_dbg_set_address_to_dabr), //940 (0x3AC)
NULL_FUNC(sys_dbg_get_lwmutex_information), //941 (0x3AD)
NULL_FUNC(sys_dbg_get_event_queue_list), //942 (0x3AE)
NULL_FUNC(sys_dbg_get_event_queue_information), //943 (0x3AF)
NULL_FUNC(sys_dbg_initialize_ppu_exception_handler), //944 (0x3B0)
NULL_FUNC(sys_dbg_finalize_ppu_exception_handler), //945 (0x3B1) DBG
NULL_FUNC(sys_dbg_get_semaphore_list), //946 (0x3B2)
NULL_FUNC(sys_dbg_get_semaphore_information), //947 (0x3B3)
NULL_FUNC(sys_dbg_get_kernel_thread_list), //948 (0x3B4)
NULL_FUNC(sys_dbg_get_kernel_thread_info), //949 (0x3B5)
NULL_FUNC(sys_dbg_get_lwcond_list), //950 (0x3B6)
NULL_FUNC(sys_dbg_get_lwcond_information), //951 (0x3B7)
NULL_FUNC(sys_dbg_create_scratch_data_area_ext), //952 (0x3B8)
NULL_FUNC(sys_dbg_vm_get_page_information), //953 (0x3B9)
NULL_FUNC(sys_dbg_vm_get_info), //954 (0x3BA)
NULL_FUNC(sys_dbg_enable_floating_point_enabled_exception),//955 (0x3BB)
NULL_FUNC(sys_dbg_disable_floating_point_enabled_exception),//956 (0x3BC)
NULL_FUNC(sys_dbg_get_process_memory_container_information),//957 (0x3BD)
uns_func, //958 (0x3BE) UNS
null_func,//BIND_SYSC(sys_dbg_...), //959 (0x3BF)
NULL_FUNC(sys_control_performance_monitor), //960 (0x3C0)
NULL_FUNC(sys_performance_monitor_hidden), //961 (0x3C1)
NULL_FUNC(sys_performance_monitor_bookmark), //962 (0x3C2)
NULL_FUNC(sys_lv1_pc_trace_create), //963 (0x3C3)
NULL_FUNC(sys_lv1_pc_trace_start), //964 (0x3C4)
NULL_FUNC(sys_lv1_pc_trace_stop), //965 (0x3C5)
NULL_FUNC(sys_lv1_pc_trace_get_status), //966 (0x3C6)
NULL_FUNC(sys_lv1_pc_trace_destroy), //967 (0x3C7)
NULL_FUNC(sys_rsx_trace_ioctl), //968 (0x3C8)
null_func,//BIND_SYSC(sys_dbg_...), //969 (0x3C9)
NULL_FUNC(sys_dbg_get_event_flag_list), //970 (0x3CA)
NULL_FUNC(sys_dbg_get_event_flag_information), //971 (0x3CB)
null_func,//BIND_SYSC(sys_dbg_...), //972 (0x3CC)
uns_func,//BIND_SYSC(sys_dbg_...), //973 (0x3CD)
null_func,//BIND_SYSC(sys_dbg_...), //974 (0x3CE)
NULL_FUNC(sys_dbg_read_spu_thread_context2), //975 (0x3CF)
BIND_SYSC(sys_crypto_engine_create), //976 (0x3D0)
BIND_SYSC(sys_crypto_engine_destroy), //977 (0x3D1)
NULL_FUNC(sys_crypto_engine_hasher_prepare), //978 (0x3D2) ROOT
NULL_FUNC(sys_crypto_engine_hasher_run), //979 (0x3D3)
NULL_FUNC(sys_crypto_engine_hasher_get_hash), //980 (0x3D4)
NULL_FUNC(sys_crypto_engine_cipher_prepare), //981 (0x3D5) ROOT
NULL_FUNC(sys_crypto_engine_cipher_run), //982 (0x3D6)
NULL_FUNC(sys_crypto_engine_cipher_get_hash), //983 (0x3D7)
BIND_SYSC(sys_crypto_engine_random_generate), //984 (0x3D8)
NULL_FUNC(sys_dbg_get_console_type), //985 (0x3D9) ROOT
null_func,//BIND_SYSC(sys_dbg_...), //986 (0x3DA) ROOT DBG
null_func,//BIND_SYSC(sys_dbg_...), //987 (0x3DB) ROOT
null_func,//BIND_SYSC(sys_dbg_..._ppu_exception_handler) //988 (0x3DC)
null_func,//BIND_SYSC(sys_dbg_...), //989 (0x3DD)
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //990-998 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //999-1007 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //1008-1016 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //1020-1023 UNS
};
#undef BIND_SYSC
#undef NULL_FUNC
// TODO: more enums
enum CellAdecError : u32;
enum CellAtracError : u32;
enum CellAtracMultiError : u32;
enum CellAudioError : u32;
enum CellAudioOutError : u32;
enum CellAudioInError : u32;
enum CellVideoOutError : u32;
enum CellSpursCoreError : u32;
enum CellSpursPolicyModuleError : u32;
enum CellSpursTaskError : u32;
enum CellSpursJobError : u32;
enum CellGameError : u32;
enum CellGameDataError : u32;
enum CellDiscGameError : u32;
enum CellHddGameError : u32;
enum SceNpTrophyError : u32;
enum SceNpError : u32;
template <u64 EnumMin, typename E>
constexpr auto formatter_of = std::make_pair(EnumMin, &fmt_class_string<E>::format);
const std::map<u64, void(*)(std::string&, u64)> s_error_codes_formatting_by_type
{
formatter_of<0x80610000, CellAdecError>,
formatter_of<0x80612100, CellAdecError>,
formatter_of<0x80610300, CellAtracError>,
formatter_of<0x80610b00, CellAtracMultiError>,
formatter_of<0x80310700, CellAudioError>,
formatter_of<0x8002b240, CellAudioOutError>,
formatter_of<0x8002b260, CellAudioInError>,
formatter_of<0x8002b220, CellVideoOutError>,
formatter_of<0x80410700, CellSpursCoreError>,
formatter_of<0x80410800, CellSpursPolicyModuleError>,
formatter_of<0x80410900, CellSpursTaskError>,
formatter_of<0x80410A00, CellSpursJobError>,
formatter_of<0x8002cb00, CellGameError>,
formatter_of<0x8002b600, CellGameDataError>,
formatter_of<0x8002bd00, CellDiscGameError>,
formatter_of<0x8002ba00, CellHddGameError>,
formatter_of<0x80022900, SceNpTrophyError>,
formatter_of<0x80029500, SceNpError>,
};
template<>
void fmt_class_string<CellError>::format(std::string& out, u64 arg)
{
// Test if can be formatted by this formatter
const bool lv2_cell_error = (arg >> 8) == 0x800100u;
if (!lv2_cell_error)
{
// Format by external enum formatters
auto upper = s_error_codes_formatting_by_type.upper_bound(arg);
if (upper == s_error_codes_formatting_by_type.begin())
{
// Format as unknown by another enum formatter
upper->second(out, arg);
return;
}
// Find the formatter whose base is the highest that is not more than arg
const auto found = std::prev(upper);
found->second(out, arg);
return;
}
format_enum(out, arg, [](auto error)
{
switch (error)
{
STR_CASE(CELL_EAGAIN);
STR_CASE(CELL_EINVAL);
STR_CASE(CELL_ENOSYS);
STR_CASE(CELL_ENOMEM);
STR_CASE(CELL_ESRCH);
STR_CASE(CELL_ENOENT);
STR_CASE(CELL_ENOEXEC);
STR_CASE(CELL_EDEADLK);
STR_CASE(CELL_EPERM);
STR_CASE(CELL_EBUSY);
STR_CASE(CELL_ETIMEDOUT);
STR_CASE(CELL_EABORT);
STR_CASE(CELL_EFAULT);
STR_CASE(CELL_ENOCHILD);
STR_CASE(CELL_ESTAT);
STR_CASE(CELL_EALIGN);
STR_CASE(CELL_EKRESOURCE);
STR_CASE(CELL_EISDIR);
STR_CASE(CELL_ECANCELED);
STR_CASE(CELL_EEXIST);
STR_CASE(CELL_EISCONN);
STR_CASE(CELL_ENOTCONN);
STR_CASE(CELL_EAUTHFAIL);
STR_CASE(CELL_ENOTMSELF);
STR_CASE(CELL_ESYSVER);
STR_CASE(CELL_EAUTHFATAL);
STR_CASE(CELL_EDOM);
STR_CASE(CELL_ERANGE);
STR_CASE(CELL_EILSEQ);
STR_CASE(CELL_EFPOS);
STR_CASE(CELL_EINTR);
STR_CASE(CELL_EFBIG);
STR_CASE(CELL_EMLINK);
STR_CASE(CELL_ENFILE);
STR_CASE(CELL_ENOSPC);
STR_CASE(CELL_ENOTTY);
STR_CASE(CELL_EPIPE);
STR_CASE(CELL_EROFS);
STR_CASE(CELL_ESPIPE);
STR_CASE(CELL_E2BIG);
STR_CASE(CELL_EACCES);
STR_CASE(CELL_EBADF);
STR_CASE(CELL_EIO);
STR_CASE(CELL_EMFILE);
STR_CASE(CELL_ENODEV);
STR_CASE(CELL_ENOTDIR);
STR_CASE(CELL_ENXIO);
STR_CASE(CELL_EXDEV);
STR_CASE(CELL_EBADMSG);
STR_CASE(CELL_EINPROGRESS);
STR_CASE(CELL_EMSGSIZE);
STR_CASE(CELL_ENAMETOOLONG);
STR_CASE(CELL_ENOLCK);
STR_CASE(CELL_ENOTEMPTY);
STR_CASE(CELL_ENOTSUP);
STR_CASE(CELL_EFSSPECIFIC);
STR_CASE(CELL_EOVERFLOW);
STR_CASE(CELL_ENOTMOUNTED);
STR_CASE(CELL_ENOTSDATA);
STR_CASE(CELL_ESDKVER);
STR_CASE(CELL_ENOLICDISC);
STR_CASE(CELL_ENOLICENT);
}
return unknown;
});
}
class ppu_syscall_usage
{
// Internal buffer
std::string m_stats;
u64 m_old_stat[1024]{};
public:
// Public info collection buffers
atomic_t<u64> stat[1024]{};
void print_stats(bool force_print) noexcept
{
std::multimap<u64, u64, std::greater<u64>> usage;
for (u32 i = 0; i < 1024; i++)
{
if (u64 v = stat[i]; m_old_stat[i] != v || (force_print && v))
{
// Only add syscalls with non-zero usage counter and only if caught new calls since last print
usage.emplace(v, i);
m_old_stat[i] = v;
}
}
m_stats.clear();
for (auto&& pair : usage)
{
fmt::append(m_stats, u8"\n\t⁂ %s [%u]", ppu_get_syscall_name(pair.second), pair.first);
}
if (!m_stats.empty())
{
ppu_log.notice("PPU Syscall Usage Stats: %s", m_stats);
}
}
void operator()()
{
bool was_paused = false;
for (u32 i = 1; thread_ctrl::state() != thread_state::aborting; i++)
{
thread_ctrl::wait_for(1'000'000);
const bool is_paused = Emu.IsPaused();
// Force-print all if paused
const bool force_print = is_paused && !was_paused;
if (force_print || i % 10 == 0)
{
was_paused = is_paused;
print_stats(force_print);
}
}
}
~ppu_syscall_usage()
{
print_stats(true);
}
static constexpr auto thread_name = "PPU Syscall Usage Thread"sv;
};
extern void ppu_execute_syscall(ppu_thread& ppu, u64 code)
{
if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm)
{
code = ppu.gpr[11];
}
if (code < g_ppu_syscall_table.size())
{
g_fxo->get<named_thread<ppu_syscall_usage>>().stat[code]++;
if (const auto func = g_ppu_syscall_table[code].first)
{
#ifdef __APPLE__
pthread_jit_write_protect_np(false);
#endif
func(ppu, {}, vm::_ptr<u32>(ppu.cia), nullptr);
ppu_log.trace("Syscall '%s' (%llu) finished, r3=0x%llx", ppu_syscall_code(code), code, ppu.gpr[3]);
#ifdef __APPLE__
pthread_jit_write_protect_np(true);
// No need to flush cache lines after a syscall, since we didn't generate any code.
#endif
return;
}
}
fmt::throw_exception("Invalid syscall number (%llu)", code);
}
extern ppu_intrp_func_t ppu_get_syscall(u64 code)
{
if (code < g_ppu_syscall_table.size())
{
return g_ppu_syscall_table[code].first;
}
return nullptr;
}
std::string ppu_get_syscall_name(u64 code)
{
if (code < g_ppu_syscall_table.size() && !g_ppu_syscall_table[code].second.empty())
{
return std::string(g_ppu_syscall_table[code].second);
}
return fmt::format("syscall_%u", code);
}
DECLARE(lv2_obj::g_mutex);
DECLARE(lv2_obj::g_ppu){};
DECLARE(lv2_obj::g_pending){};
thread_local DECLARE(lv2_obj::g_to_notify){};
thread_local DECLARE(lv2_obj::g_postpone_notify_barrier){};
thread_local DECLARE(lv2_obj::g_to_awake);
// Scheduler queue for timeouts (wait until -> thread)
static std::deque<std::pair<u64, class cpu_thread*>> g_waiting;
// Threads which must call lv2_obj::sleep before the scheduler starts
static std::deque<class cpu_thread*> g_to_sleep;
static atomic_t<u64> s_yield_frequency = 0;
static atomic_t<u64> s_max_allowed_yield_tsc = 0;
static u64 s_last_yield_tsc = 0;
atomic_t<u32> g_lv2_preempts_taken = 0;
namespace cpu_counter
{
void remove(cpu_thread*) noexcept;
}
bool lv2_obj::sleep(cpu_thread& cpu, const u64 timeout)
{
// Should already be performed when using this flag
if (!g_postpone_notify_barrier)
{
prepare_for_sleep(cpu);
}
bool result = false;
const u64 current_time = get_guest_system_time();
{
std::lock_guard lock{g_mutex};
result = sleep_unlocked(cpu, timeout, current_time);
if (!g_to_awake.empty())
{
// Schedule pending entries
awake_unlocked({});
}
schedule_all(current_time);
}
if (!g_postpone_notify_barrier)
{
notify_all();
}
g_to_awake.clear();
return result;
}
bool lv2_obj::awake(cpu_thread* thread, s32 prio)
{
bool result = false;
{
std::lock_guard lock(g_mutex);
result = awake_unlocked(thread, prio);
schedule_all();
}
if (result)
{
if (auto cpu = cpu_thread::get_current(); cpu && cpu->is_paused())
{
vm::temporary_unlock();
}
}
if (!g_postpone_notify_barrier)
{
notify_all();
}
return result;
}
bool lv2_obj::yield(cpu_thread& thread)
{
if (auto ppu = thread.try_get<ppu_thread>())
{
ppu->raddr = 0; // Clear reservation
if (!atomic_storage<ppu_thread*>::load(ppu->next_ppu))
{
// Nothing to do
return false;
}
}
return awake(&thread, yield_cmd);
}
bool lv2_obj::sleep_unlocked(cpu_thread& thread, u64 timeout, u64 current_time)
{
const u64 start_time = current_time;
auto on_to_sleep_update = [&]()
{
std::string out = fmt::format("Threads (%d):", g_to_sleep.size());
for (auto thread : g_to_sleep)
{
fmt::append(out, " 0x%x,", thread->id);
}
ppu_log.warning("%s", out);
if (g_to_sleep.empty())
{
// All threads are ready, wake threads
Emu.CallFromMainThread([]
{
if (Emu.IsStarting())
{
// It uses lv2_obj::g_mutex, run it on main thread
Emu.FinalizeRunRequest();
}
});
}
};
bool return_val = true;
if (auto ppu = thread.try_get<ppu_thread>())
{
ppu_log.trace("sleep() - waiting (%zu)", g_pending);
if (ppu->ack_suspend)
{
ppu->ack_suspend = false;
g_pending--;
}
if (std::exchange(ppu->cancel_sleep, 0) == 2)
{
// Signal that the underlying LV2 operation has been cancelled and replaced with a short yield
return_val = false;
}
const auto [_, ok] = ppu->state.fetch_op([&](bs_t<cpu_flag>& val)
{
if (!(val & cpu_flag::signal))
{
val += cpu_flag::suspend;
// Flag used for forced timeout notification
ensure(!timeout || !(val & cpu_flag::notify));
return true;
}
return false;
});
if (!ok)
{
ppu_log.fatal("sleep() failed (signaled) (%s)", ppu->current_function);
return false;
}
// Find and remove the thread
if (!unqueue(g_ppu, ppu, &ppu_thread::next_ppu))
{
if (auto it = std::find(g_to_sleep.begin(), g_to_sleep.end(), ppu); it != g_to_sleep.end())
{
g_to_sleep.erase(it);
ppu->start_time = start_time;
on_to_sleep_update();
return true;
}
// Already sleeping
ppu_log.trace("sleep(): called on already sleeping thread.");
return false;
}
ppu->raddr = 0; // Clear reservation
ppu->start_time = start_time;
ppu->end_time = timeout ? start_time + std::min<u64>(timeout, ~start_time) : u64{umax};
}
else if (auto spu = thread.try_get<spu_thread>())
{
if (auto it = std::find(g_to_sleep.begin(), g_to_sleep.end(), spu); it != g_to_sleep.end())
{
g_to_sleep.erase(it);
on_to_sleep_update();
return true;
}
return false;
}
if (timeout)
{
const u64 wait_until = start_time + std::min<u64>(timeout, ~start_time);
// Register timeout if necessary
for (auto it = g_waiting.cbegin(), end = g_waiting.cend();; it++)
{
if (it == end || it->first > wait_until)
{
g_waiting.emplace(it, wait_until, &thread);
break;
}
}
}
return return_val;
}
bool lv2_obj::awake_unlocked(cpu_thread* cpu, s32 prio)
{
// Check thread type
AUDIT(!cpu || cpu->id_type() == 1);
switch (prio)
{
default:
{
// Priority set
if (static_cast<ppu_thread*>(cpu)->prio.exchange(prio) == prio || !unqueue(g_ppu, static_cast<ppu_thread*>(cpu), &ppu_thread::next_ppu))
{
return true;
}
break;
}
case yield_cmd:
{
usz i = 0;
// Yield command
for (auto ppu_next = &g_ppu;; i++)
{
const auto ppu = +*ppu_next;
if (!ppu)
{
return false;
}
if (ppu == cpu)
{
auto ppu2 = ppu->next_ppu;
if (!ppu2 || ppu2->prio != ppu->prio)
{
// Empty 'same prio' threads list
return false;
}
for (i++;; i++)
{
const auto next = ppu2->next_ppu;
if (!next || next->prio != ppu->prio)
{
break;
}
ppu2 = next;
}
// Rotate current thread to the last position of the 'same prio' threads list
// Exchange forward pointers
*ppu_next = std::exchange(ppu->next_ppu, std::exchange(ppu2->next_ppu, ppu));
if (i < g_cfg.core.ppu_threads + 0u)
{
// Threads were rotated, but no context switch was made
return false;
}
ppu->start_time = get_guest_system_time();
break;
}
ppu_next = &ppu->next_ppu;
}
break;
}
case enqueue_cmd:
{
break;
}
}
const auto emplace_thread = [](cpu_thread* const cpu)
{
for (auto it = &g_ppu;;)
{
const auto next = +*it;
if (next == cpu)
{
ppu_log.trace("sleep() - suspended (p=%zu)", g_pending);
if (static_cast<ppu_thread*>(cpu)->cancel_sleep == 1)
{
// The next sleep call of the thread is cancelled
static_cast<ppu_thread*>(cpu)->cancel_sleep = 2;
}
return false;
}
// Use priority, also preserve FIFO order
if (!next || next->prio > static_cast<ppu_thread*>(cpu)->prio)
{
atomic_storage<ppu_thread*>::release(static_cast<ppu_thread*>(cpu)->next_ppu, next);
atomic_storage<ppu_thread*>::release(*it, static_cast<ppu_thread*>(cpu));
break;
}
it = &next->next_ppu;
}
// Unregister timeout if necessary
for (auto it = g_waiting.cbegin(), end = g_waiting.cend(); it != end; it++)
{
if (it->second == cpu)
{
g_waiting.erase(it);
break;
}
}
ppu_log.trace("awake(): %s", cpu->id);
return true;
};
// Yield changed the queue before
bool changed_queue = prio == yield_cmd;
if (cpu && prio != yield_cmd)
{
// Emplace current thread
if (emplace_thread(cpu))
{
changed_queue = true;
}
}
else for (const auto _cpu : g_to_awake)
{
// Emplace threads from list
if (emplace_thread(_cpu))
{
changed_queue = true;
}
}
auto target = +g_ppu;
// Suspend threads if necessary
for (usz i = 0, thread_count = g_cfg.core.ppu_threads; target; target = target->next_ppu, i++)
{
if (i >= thread_count && cpu_flag::suspend - target->state)
{
ppu_log.trace("suspend(): %s", target->id);
target->ack_suspend = true;
g_pending++;
ensure(!target->state.test_and_set(cpu_flag::suspend));
if (is_paused(target->state - cpu_flag::suspend))
{
target->state.notify_one(cpu_flag::suspend);
}
}
}
const auto current_ppu = cpu_thread::get_current<ppu_thread>();
// Remove pending if necessary
if (current_ppu)
{
if (std::exchange(current_ppu->ack_suspend, false))
{
ensure(g_pending)--;
}
}
return changed_queue;
}
void lv2_obj::cleanup()
{
g_ppu = nullptr;
g_to_sleep.clear();
g_waiting.clear();
g_pending = 0;
s_yield_frequency = 0;
}
void lv2_obj::schedule_all(u64 current_time)
{
usz notify_later_idx = 0;
if (!g_pending && g_to_sleep.empty())
{
auto target = +g_ppu;
// Wake up threads
for (usz x = g_cfg.core.ppu_threads; target && x; target = target->next_ppu, x--)
{
if (target->state & cpu_flag::suspend)
{
ppu_log.trace("schedule(): %s", target->id);
target->start_time = 0;
if ((target->state.fetch_op(FN(x += cpu_flag::signal, x -= cpu_flag::suspend, void())) & (cpu_flag::wait + cpu_flag::signal)) != cpu_flag::wait)
{
continue;
}
if (notify_later_idx == std::size(g_to_notify))
{
// Out of notification slots, notify locally (resizable container is not worth it)
target->state.notify_one(cpu_flag::signal + cpu_flag::suspend);
}
else
{
g_to_notify[notify_later_idx++] = &target->state;
}
}
}
}
// Check registered timeouts
while (!g_waiting.empty())
{
const auto pair = &g_waiting.front();
if (!current_time)
{
current_time = get_guest_system_time();
}
if (pair->first <= current_time)
{
const auto target = pair->second;
g_waiting.pop_front();
if (target != cpu_thread::get_current())
{
// Change cpu_thread::state for the lightweight notification to work
ensure(!target->state.test_and_set(cpu_flag::notify));
// Otherwise notify it to wake itself
if (notify_later_idx == std::size(g_to_notify))
{
// Out of notification slots, notify locally (resizable container is not worth it)
target->state.notify_one(cpu_flag::notify);
}
else
{
g_to_notify[notify_later_idx++] = &target->state;
}
}
}
else
{
// The list is sorted so assume no more timeouts
break;
}
}
if (notify_later_idx - 1 < std::size(g_to_notify) - 1)
{
// Null-terminate the list if it ends before last slot
g_to_notify[notify_later_idx] = nullptr;
}
if (const u64 freq = s_yield_frequency)
{
const u64 tsc = utils::get_tsc();
const u64 last_tsc = s_last_yield_tsc;
if (tsc >= last_tsc && tsc <= s_max_allowed_yield_tsc && tsc - last_tsc >= freq)
{
auto target = +g_ppu;
cpu_thread* cpu = nullptr;
for (usz x = g_cfg.core.ppu_threads;; target = target->next_ppu, x--)
{
if (!target || !x)
{
if (g_ppu && cpu_flag::preempt - g_ppu->state)
{
// Don't be picky, pick up any running PPU thread even it has a wait flag
cpu = g_ppu;
}
// TODO: If this case is common enough it may be valuable to iterate over all CPU threads to find a perfect candidate (one without a wait or suspend flag)
else if (auto current = cpu_thread::get_current(); current && cpu_flag::suspend - current->state)
{
// May be an SPU or RSX thread, use them as a last resort
cpu = current;
}
break;
}
if (target->state.none_of(cpu_flag::preempt + cpu_flag::wait))
{
cpu = target;
break;
}
}
if (cpu && cpu_flag::preempt - cpu->state && !cpu->state.test_and_set(cpu_flag::preempt))
{
s_last_yield_tsc = tsc;
g_lv2_preempts_taken.release(g_lv2_preempts_taken.load() + 1); // Has a minor race but performance is more important
rsx::set_rsx_yield_flag();
}
}
}
}
ppu_thread_status lv2_obj::ppu_state(ppu_thread* ppu, bool lock_idm, bool lock_lv2)
{
std::optional<reader_lock> opt_lock[2];
if (lock_idm)
{
opt_lock[0].emplace(id_manager::g_mutex);
}
if (!Emu.IsReady() ? ppu->state.all_of(cpu_flag::stop) : ppu->stop_flag_removal_protection)
{
return PPU_THREAD_STATUS_IDLE;
}
switch (ppu->joiner)
{
case ppu_join_status::zombie: return PPU_THREAD_STATUS_ZOMBIE;
case ppu_join_status::exited: return PPU_THREAD_STATUS_DELETED;
default: break;
}
if (lock_lv2)
{
opt_lock[1].emplace(lv2_obj::g_mutex);
}
usz pos = umax;
usz i = 0;
for (auto target = +g_ppu; target; target = target->next_ppu, i++)
{
if (target == ppu)
{
pos = i;
break;
}
}
if (pos == umax)
{
if (!ppu->interrupt_thread_executing)
{
return PPU_THREAD_STATUS_STOP;
}
return PPU_THREAD_STATUS_SLEEP;
}
if (pos >= g_cfg.core.ppu_threads + 0u)
{
return PPU_THREAD_STATUS_RUNNABLE;
}
return PPU_THREAD_STATUS_ONPROC;
}
void lv2_obj::set_future_sleep(cpu_thread* cpu)
{
g_to_sleep.emplace_back(cpu);
}
bool lv2_obj::is_scheduler_ready()
{
reader_lock lock(g_mutex);
return g_to_sleep.empty();
}
bool lv2_obj::has_ppus_in_running_state()
{
auto target = atomic_storage<ppu_thread*>::load(g_ppu);
for (usz i = 0, thread_count = g_cfg.core.ppu_threads; target; target = atomic_storage<ppu_thread*>::load(target->next_ppu), i++)
{
if (i >= thread_count)
{
return true;
}
}
return false;
}
void lv2_obj::set_yield_frequency(u64 freq, u64 max_allowed_tsc)
{
s_yield_frequency.release(freq);
s_max_allowed_yield_tsc.release(max_allowed_tsc);
g_lv2_preempts_taken.release(0);
}
bool lv2_obj::wait_timeout(u64 usec, ppu_thread* cpu, bool scale, bool is_usleep)
{
static_assert(u64{umax} / max_timeout >= 100, "max timeout is not valid for scaling");
const u64 start_time = get_system_time();
if (cpu)
{
if (u64 end_time = cpu->end_time; end_time != umax)
{
const u64 guest_start = get_guest_system_time(start_time);
if (end_time <= guest_start)
{
return true;
}
usec = end_time - guest_start;
scale = true;
}
}
if (scale)
{
// Scale time
usec = std::min<u64>(usec, u64{umax} / 100) * 100 / g_cfg.core.clocks_scale;
}
// Clamp
usec = std::min<u64>(usec, max_timeout);
u64 passed = 0;
atomic_bs_t<cpu_flag> dummy{};
const auto& state = cpu ? cpu->state : dummy;
auto old_state = +state;
auto wait_for = [&](u64 timeout)
{
thread_ctrl::wait_on(state, old_state, timeout);
};
for (;; old_state = state)
{
if (old_state & cpu_flag::notify)
{
// Timeout notification has been forced
break;
}
if (old_state & cpu_flag::signal)
{
return false;
}
if (::is_stopped(old_state) || thread_ctrl::state() == thread_state::aborting)
{
return passed >= usec;
}
if (passed >= usec)
{
break;
}
u64 remaining = usec - passed;
#ifdef __linux__
// NOTE: Assumption that timer initialization has succeeded
u64 host_min_quantum = is_usleep && remaining <= 1000 ? 10 : 50;
#else
// Host scheduler quantum for windows (worst case)
// NOTE: On ps3 this function has very high accuracy
constexpr u64 host_min_quantum = 500;
#endif
// TODO: Tune for other non windows operating sytems
if (g_cfg.core.sleep_timers_accuracy < (is_usleep ? sleep_timers_accuracy_level::_usleep : sleep_timers_accuracy_level::_all_timers))
{
wait_for(remaining);
}
else
{
if (remaining > host_min_quantum)
{
#ifdef __linux__
// Do not wait for the last quantum to avoid loss of accuracy
wait_for(remaining - ((remaining % host_min_quantum) + host_min_quantum));
#else
// Wait on multiple of min quantum for large durations to avoid overloading low thread cpus
wait_for(remaining - (remaining % host_min_quantum));
#endif
}
// TODO: Determine best value for yield delay
else
{
// Try yielding. May cause long wake latency but helps weaker CPUs a lot by alleviating resource pressure
std::this_thread::yield();
}
}
passed = get_system_time() - start_time;
}
return true;
}
void lv2_obj::prepare_for_sleep(cpu_thread& cpu)
{
vm::temporary_unlock(cpu);
cpu_counter::remove(&cpu);
}