Files
PS2Recomp/ps2xRuntime/src/lib/Kernel/Syscalls/Helpers/State.h
T
2026-07-25 21:23:24 -03:00

360 lines
10 KiB
C++

#pragma once
#include <cstddef>
#include <cstdint>
inline std::unordered_map<int, FILE *> g_fileDescriptors;
inline int g_nextFd = 3; // Start after stdin, stdout, stderr
// Thread status
#define THS_RUN 0x01
#define THS_READY 0x02
#define THS_WAIT 0x04
#define THS_SUSPEND 0x08
#define THS_WAITSUSPEND 0x0c
#define THS_DORMANT 0x10
// Thread WAIT Status
#define TSW_NONE 0
#define TSW_SLEEP 1
#define TSW_SEMA 2
#define TSW_EVENT 3
// Common kernel-like error codes used by thread/event/alarm syscalls.
constexpr int KE_OK = 0;
constexpr int KE_ERROR = -1;
constexpr int KE_ILLEGAL_PRIORITY = -403;
constexpr int KE_ILLEGAL_MODE = -405;
constexpr int KE_ILLEGAL_THID = -406;
constexpr int KE_UNKNOWN_THID = -407;
constexpr int KE_UNKNOWN_SEMID = -408;
constexpr int KE_UNKNOWN_EVFID = -409;
constexpr int KE_DORMANT = -413;
constexpr int KE_NOT_DORMANT = -414;
constexpr int KE_NOT_SUSPEND = -415;
constexpr int KE_NOT_WAIT = -416;
constexpr int KE_RELEASE_WAIT = -418;
constexpr int KE_SEMA_ZERO = -419;
constexpr int KE_SEMA_OVF = -420;
constexpr int KE_EVF_COND = -421;
constexpr int KE_EVF_MULTI = -422;
constexpr int KE_EVF_ILPAT = -423;
constexpr int KE_WAIT_DELETE = -425;
// SIF RPC Structures
struct t_SifRpcHeader
{
uint32_t pkt_addr; // void*
uint32_t rpc_id;
int sema_id;
uint32_t mode;
};
struct t_SifRpcClientData
{
t_SifRpcHeader hdr;
uint32_t command;
uint32_t buf; // void*
uint32_t cbuf; // void*
uint32_t end_function; // func ptr
uint32_t end_param; // void*
uint32_t server; // t_SifRpcServerData*
};
struct t_SifRpcServerData
{
int sid;
uint32_t func; // func ptr
uint32_t buf; // void*
int size;
uint32_t cfunc; // func ptr
uint32_t cbuf; // void*
int size2;
uint32_t client; // t_SifRpcClientData*
uint32_t pkt_addr; // void*
int rpc_number;
uint32_t recvbuf; // void*
int rsize;
int rmode;
int rid;
uint32_t link; // t_SifRpcServerData*
uint32_t next; // t_SifRpcServerData*
uint32_t base; // t_SifRpcDataQueue*
};
struct t_SifRpcDataQueue
{
int thread_id;
int active;
uint32_t link; // t_SifRpcServerData*
uint32_t start; // t_SifRpcServerData*
uint32_t end; // t_SifRpcServerData*
uint32_t next; // t_SifRpcDataQueue*
};
struct ee_thread_status_t
{
int status; // 0x00
uint32_t func; // 0x04
uint32_t stack; // 0x08
int stack_size; // 0x0C
uint32_t gp_reg; // 0x10
int initial_priority; // 0x14
int current_priority; // 0x18
uint32_t attr; // 0x1C
uint32_t option; // 0x20
uint32_t waitType; // 0x24
uint32_t waitId; // 0x28
uint32_t wakeupCount; // 0x2C
};
// PS2SDK EE kernel.h t_ee_thread. CreateThread consumes this full 0x24-byte
// descriptor; it is not the attr-first IOP thread descriptor.
struct ee_thread_t
{
int status;
uint32_t func;
uint32_t stack;
int stack_size;
uint32_t gp_reg;
int initial_priority;
int current_priority;
uint32_t attr;
uint32_t option;
};
static_assert(sizeof(ee_thread_t) == 0x24u);
static_assert(sizeof(ee_thread_status_t) == 0x30u);
struct ee_sema_t
{
int count;
int max_count;
int init_count;
int wait_threads;
uint32_t attr;
uint32_t option;
};
static_assert(sizeof(ee_sema_t) == 0x18u);
struct io_stat_t
{
uint32_t mode;
uint32_t attr;
uint32_t size;
uint8_t ctime[8];
uint8_t atime[8];
uint8_t mtime[8];
uint32_t hisize;
};
static constexpr uint32_t kFioSoIfLnk = 0x0008;
static constexpr uint32_t kFioSoIfReg = 0x0010;
static constexpr uint32_t kFioSoIfDir = 0x0020;
static constexpr uint32_t kFioSoIROth = 0x0004;
static constexpr uint32_t kFioSoIWOth = 0x0002;
static constexpr uint32_t kFioSoIXOth = 0x0001;
inline std::mutex g_fd_mutex;
struct RpcServerState
{
uint32_t sid = 0;
uint32_t sd_ptr = 0; // PS2 address
};
struct RpcClientState
{
bool busy = false;
uint32_t last_rpc = 0;
uint32_t sid = 0;
};
struct SifRpcDebugEvent
{
uint64_t seq = 0;
const char *op = "";
uint32_t pc = 0;
uint32_t ra = 0;
uint32_t threadId = 0;
uint32_t sid = 0;
uint32_t rpcNum = 0;
uint32_t clientPtr = 0;
uint32_t serverPtr = 0;
uint32_t sendBuf = 0;
uint32_t sendSize = 0;
uint32_t recvBuf = 0;
uint32_t recvSize = 0;
uint32_t resultPtr = 0;
uint32_t mode = 0;
uint32_t endFunc = 0;
uint32_t endParam = 0;
uint32_t semaId = 0;
uint32_t flags = 0;
uint32_t sendPreviewSize = 0;
uint32_t recvPreviewSize = 0;
uint8_t sendPreview[16]{};
uint8_t recvPreview[16]{};
int32_t result = 0;
};
static constexpr size_t kSifRpcDebugHistoryCount = 256u;
static constexpr size_t kSifRpcDebugPreviewBytes = 16u;
static constexpr uint32_t kSifRpcDebugFlagNowait = 1u << 0;
static constexpr uint32_t kSifRpcDebugFlagHandledByHle = 1u << 1;
static constexpr uint32_t kSifRpcDebugFlagCallback = 1u << 2;
static constexpr uint32_t kSifRpcDebugFlagMissingClient = 1u << 3;
static constexpr uint32_t kSifRpcDebugFlagServerDispatch = 1u << 4;
static constexpr uint32_t kSifRpcDebugFlagUnhandled = 1u << 6;
static constexpr uint32_t kSifRpcDebugFlagFallbackCopy = 1u << 7;
static constexpr uint32_t kSifRpcDebugFlagFallbackZero = 1u << 8;
inline std::unordered_map<uint32_t, RpcServerState> g_rpc_servers;
inline std::unordered_map<uint32_t, RpcClientState> g_rpc_clients;
inline SifRpcDebugEvent g_sif_rpc_debug_history[kSifRpcDebugHistoryCount]{};
inline uint64_t g_sif_rpc_debug_next_seq = 0;
inline std::mutex g_rpc_mutex;
inline std::recursive_mutex g_sif_call_rpc_mutex;
inline bool g_rpc_initialized = false;
inline uint32_t g_rpc_next_id = 1;
inline uint32_t g_rpc_packet_index = 0;
inline uint32_t g_rpc_server_index = 0;
inline uint32_t g_rpc_active_queue = 0;
inline std::mutex g_bootmode_mutex;
inline bool g_bootmode_initialized = false;
inline uint32_t g_bootmode_pool_offset = 0;
inline std::unordered_map<uint8_t, uint32_t> g_bootmode_addresses;
static constexpr uint32_t kGuestSyscallTableGuestBase = 0x80011F80u;
static constexpr uint32_t kGuestSyscallTablePhysBase = kGuestSyscallTableGuestBase & 0x1FFFFFFFu;
static constexpr uint32_t kGuestSyscallMirrorLimit = 0x00080000u;
static constexpr uint32_t kGuestSyscallTableProbeBase = 0x000002F0u;
inline std::mutex g_tls_mutex;
inline uint32_t g_tls_index = 0;
inline std::mutex g_osd_mutex;
inline bool g_osd_config_initialized = false;
inline uint32_t g_osd_config_raw = 0;
inline uint32_t g_osd_config2_raw = 0;
inline std::mutex g_ps2_path_mutex;
inline bool g_ps2_paths_initialized = false;
inline std::filesystem::path g_host_base;
inline std::filesystem::path g_cdrom_base;
inline std::filesystem::path g_host_cwd;
inline std::filesystem::path g_cdrom_cwd;
inline std::string g_ps2_cwd_device = "host0";
static constexpr uint32_t kRpcPacketSize = 64;
static constexpr uint32_t kRpcPacketPoolBase = 0x01F00000;
static constexpr uint32_t kRpcPacketPoolBytes = 0x00010000;
static constexpr uint32_t kRpcPacketPoolCount = kRpcPacketPoolBytes / kRpcPacketSize;
static constexpr uint32_t kRpcServerPoolBase = 0x01F10000;
static constexpr uint32_t kRpcServerPoolBytes = 0x00010000;
static constexpr uint32_t kRpcServerStride = 0x80;
static constexpr uint32_t kRpcServerPoolCount = kRpcServerPoolBytes / kRpcServerStride;
static constexpr uint32_t kTlsPoolBase = 0x01F20000;
static constexpr uint32_t kTlsPoolBytes = 0x00010000;
static constexpr uint32_t kTlsBlockSize = 0x100;
static constexpr uint32_t kTlsPoolCount = kTlsPoolBytes / kTlsBlockSize;
static constexpr uint32_t kBootModePoolBase = 0x01F30000;
static constexpr uint32_t kBootModePoolBytes = 0x00001000;
static constexpr uint32_t kSifRpcModeNowait = 0x01;
static constexpr uint32_t kSifRpcModeNoWbDc = 0x02;
static constexpr size_t kMaxSifModulePathBytes = 260;
static constexpr uint32_t kMaxSifModuleLogs = 24;
static constexpr size_t kSifModuleBufferProbeBytes = 2048;
static constexpr size_t kLoadfilePathMaxBytes = 252;
static constexpr size_t kLoadfileArgMaxBytes = 252;
static constexpr uint32_t kElfMagic = 0x464C457Fu;
static constexpr uint16_t kElfMachineMips = 8u;
static constexpr uint16_t kElfTypeExec = 2u;
static constexpr uint32_t kElfPtLoad = 1u;
static constexpr uint32_t kElfPtMipsRegInfo = 0x70000000u;
static constexpr uint32_t kElfShtMipsRegInfo = 0x70000006u;
#pragma pack(push, 1)
struct Elf32Header
{
uint32_t magic;
uint8_t elfClass;
uint8_t endianness;
uint8_t version;
uint8_t osAbi;
uint8_t abiVersion;
uint8_t pad[7];
uint16_t type;
uint16_t machine;
uint32_t version2;
uint32_t entry;
uint32_t phoff;
uint32_t shoff;
uint32_t flags;
uint16_t ehsize;
uint16_t phentsize;
uint16_t phnum;
uint16_t shentsize;
uint16_t shnum;
uint16_t shstrndx;
};
struct Elf32ProgramHeader
{
uint32_t type;
uint32_t offset;
uint32_t vaddr;
uint32_t paddr;
uint32_t filesz;
uint32_t memsz;
uint32_t flags;
uint32_t align;
};
struct Elf32SectionHeader
{
uint32_t name;
uint32_t type;
uint32_t flags;
uint32_t addr;
uint32_t offset;
uint32_t size;
uint32_t link;
uint32_t info;
uint32_t addralign;
uint32_t entsize;
};
struct GuestExecData
{
uint32_t epc;
uint32_t gp;
uint32_t sp;
uint32_t dummy;
};
#pragma pack(pop)
static_assert(sizeof(Elf32Header) == 52u, "Unexpected ELF32 header layout.");
static_assert(sizeof(Elf32ProgramHeader) == 32u, "Unexpected ELF32 program header layout.");
static_assert(sizeof(Elf32SectionHeader) == 40u, "Unexpected ELF32 section header layout.");
static_assert(sizeof(GuestExecData) == 16u, "Unexpected GuestExecData layout.");
struct SifModuleRecord
{
int32_t id = 0;
std::string path;
std::string pathKey;
uint32_t refCount = 0;
bool loaded = false;
};
inline std::mutex g_sif_module_mutex;
inline std::unordered_map<int32_t, SifModuleRecord> g_sif_modules_by_id;
inline std::unordered_map<std::string, int32_t> g_sif_module_id_by_path;
inline int32_t g_next_sif_module_id = 1;
inline uint32_t g_sif_module_log_count = 0;