rpcsx/rpcs3/Emu/ARMv7/PSVFuncList.h
2015-08-01 14:39:03 +03:00

685 lines
20 KiB
C++

#pragma once
#include "Emu/Memory/Memory.h"
#include "ARMv7Context.h"
#include "Emu/SysCalls/LogBase.h"
namespace vm { using namespace psv; }
// PSV module class
class psv_log_base : public LogBase
{
using init_func_t = void(*)();
std::string m_name;
init_func_t m_init;
public:
std::function<void()> on_load;
std::function<void()> on_unload;
std::function<void()> on_stop;
std::function<void(s32 error, struct psv_func* func)> on_error;
public:
psv_log_base(const std::string& name, init_func_t init);
void Init()
{
on_load = nullptr;
on_unload = nullptr;
on_stop = nullptr;
on_error = nullptr;
m_init();
}
virtual const std::string& GetName() const override
{
return m_name;
}
};
using armv7_func_caller = void(*)(ARMv7Context&);
struct armv7_va_args_t
{
u32 g_count;
u32 f_count;
u32 v_count;
};
// Utilities for binding ARMv7Context to C++ function arguments received by HLE functions or sent to callbacks
namespace psv_func_detail
{
enum arg_class : u32
{
ARG_GENERAL,
ARG_FLOAT,
ARG_VECTOR,
ARG_STACK,
ARG_CONTEXT,
ARG_VARIADIC,
ARG_UNKNOWN,
};
static const auto FIXED_STACK_FRAME_SIZE = 0x80; // described in CB_FUNC.h
template<typename T, arg_class type, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg
{
static_assert(type == ARG_GENERAL, "Unknown function argument type");
static_assert(!std::is_pointer<T>::value, "Invalid function argument type (pointer)");
static_assert(!std::is_reference<T>::value, "Invalid function argument type (reference)");
static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_GENERAL");
force_inline static T get_arg(ARMv7Context& context)
{
return cast_from_armv7_gpr<T>(context.GPR[g_count - 1]);
}
force_inline static void put_arg(ARMv7Context& context, const T& arg)
{
context.GPR[g_count - 1] = cast_to_armv7_gpr<T>(arg);
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<u64, ARG_GENERAL, g_count, f_count, v_count>
{
// first u64 argument is passed in r0-r1, second one is passed in r2-r3 (if g_count = 3)
static_assert(g_count == 2 || g_count == 4, "Wrong u64 argument position");
force_inline static u64 get_arg(ARMv7Context& context)
{
return context.GPR_D[(g_count - 1) >> 1];
}
force_inline static void put_arg(ARMv7Context& context, u64 arg)
{
context.GPR_D[(g_count - 1) >> 1] = arg;
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<s64, ARG_GENERAL, g_count, f_count, v_count>
{
static_assert(g_count == 2 || g_count == 4, "Wrong s64 argument position");
force_inline static s64 get_arg(ARMv7Context& context)
{
return context.GPR_D[(g_count - 1) >> 1];
}
force_inline static void put_arg(ARMv7Context& context, s64 arg)
{
context.GPR_D[(g_count - 1) >> 1] = arg;
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_FLOAT, g_count, f_count, v_count>
{
static_assert(f_count <= 0, "TODO: Unsupported argument type (float)");
static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT");
force_inline static T get_arg(ARMv7Context& context)
{
}
force_inline static void put_arg(ARMv7Context& context, const T& arg)
{
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count>
{
static_assert(v_count <= 0, "TODO: Unsupported argument type (vector)");
static_assert(std::is_same<std::remove_cv_t<T>, u128>::value, "Invalid function argument type for ARG_VECTOR");
force_inline static T get_arg(ARMv7Context& context)
{
}
force_inline static void put_arg(ARMv7Context& context, const T& arg)
{
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_STACK, g_count, f_count, v_count>
{
static_assert(f_count <= 0, "TODO: Unsupported stack argument type (float)");
static_assert(v_count <= 0, "TODO: Unsupported stack argument type (vector)");
static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_STACK");
force_inline static T get_arg(ARMv7Context& context)
{
// TODO: check
return cast_from_armv7_gpr<T>(vm::read32(context.SP + sizeof(u32) * (g_count - 5)));
}
force_inline static void put_arg(ARMv7Context& context, const T& arg)
{
// TODO: check
const int stack_pos = (g_count - 5) * 4 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < 0, "TODO: Increase fixed stack frame size (arg count limit broken)");
vm::write32(context.SP + stack_pos, cast_to_armv7_gpr<T>(arg));
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<u64, ARG_STACK, g_count, f_count, v_count>
{
force_inline static u64 get_arg(ARMv7Context& context)
{
// TODO: check
return vm::read64(context.SP + sizeof(u32) * (g_count - 6));
}
force_inline static void put_arg(ARMv7Context& context, u64 arg)
{
// TODO: check
const int stack_pos = (g_count - 6) * 4 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < -4, "TODO: Increase fixed stack frame size (arg count limit broken)");
vm::write64(context.SP + stack_pos, arg);
}
};
template<u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<s64, ARG_STACK, g_count, f_count, v_count>
{
force_inline static s64 get_arg(ARMv7Context& context)
{
// TODO: check
return vm::read64(context.SP + sizeof(u32) * (g_count - 6));
}
force_inline static void put_arg(ARMv7Context& context, s64 arg)
{
// TODO: check
const int stack_pos = (g_count - 6) * 4 - FIXED_STACK_FRAME_SIZE;
static_assert(stack_pos < -4, "TODO: Increase fixed stack frame size (arg count limit broken)");
vm::write64(context.SP + stack_pos, arg);
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_CONTEXT, g_count, f_count, v_count>
{
static_assert(std::is_same<T, ARMv7Context&>::value, "Invalid function argument type for ARG_CONTEXT");
force_inline static ARMv7Context& get_arg(ARMv7Context& context)
{
return context;
}
force_inline static void put_arg(ARMv7Context& context, ARMv7Context& arg)
{
}
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct bind_arg<T, ARG_VARIADIC, g_count, f_count, v_count>
{
static_assert(std::is_same<std::remove_cv_t<T>, armv7_va_args_t>::value, "Invalid function argument type for ARG_VARIADIC");
force_inline static armv7_va_args_t get_arg(ARMv7Context& context)
{
return{ g_count, f_count, v_count };
}
};
template<typename T, arg_class type>
struct bind_result
{
static_assert(type != ARG_FLOAT, "TODO: Unsupported funcion result type (float)");
static_assert(type != ARG_VECTOR, "TODO: Unsupported funcion result type (vector)");
static_assert(type == ARG_GENERAL, "Wrong use of bind_result template");
static_assert(sizeof(T) <= 4, "Invalid function result type for ARG_GENERAL");
force_inline static T get_result(ARMv7Context& context)
{
return cast_from_armv7_gpr<T>(context.GPR[0]);
}
force_inline static void put_result(ARMv7Context& context, const T& result)
{
context.GPR[0] = cast_to_armv7_gpr<T>(result);
}
};
template<>
struct bind_result<u64, ARG_GENERAL>
{
force_inline static u64 get_result(ARMv7Context& context)
{
return context.GPR_D[0];
}
force_inline static void put_result(ARMv7Context& context, u64 result)
{
context.GPR_D[0] = result;
}
};
template<>
struct bind_result<s64, ARG_GENERAL>
{
force_inline static s64 get_result(ARMv7Context& context)
{
return context.GPR_D[0];
}
force_inline static void put_result(ARMv7Context& context, s64 result)
{
context.GPR_D[0] = result;
}
};
//template<typename T>
//struct bind_result<T, ARG_FLOAT>
//{
// static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT");
// static force_inline void put_result(ARMv7Context& context, const T& result)
// {
// }
//};
//template<typename T>
//struct bind_result<T, ARG_VECTOR>
//{
// static_assert(std::is_same<std::remove_cv_t<T>, u128>::value, "Invalid function result type for ARG_VECTOR");
// static force_inline void put_result(ARMv7Context& context, const T& result)
// {
// }
//};
template<typename RT>
struct result_type
{
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
static const bool is_float = std::is_floating_point<RT>::value;
static const bool is_vector = std::is_same<std::remove_cv_t<RT>, u128>::value;
static const arg_class value = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
};
template<typename T, u32 g_count, u32 f_count, u32 v_count>
struct arg_type
{
// TODO: check calculations
static const bool is_float = std::is_floating_point<T>::value;
static const bool is_vector = std::is_same<std::remove_cv_t<T>, u128>::value;
static const bool is_context = std::is_same<T, ARMv7Context&>::value;
static const bool is_variadic = std::is_same<std::remove_cv_t<T>, armv7_va_args_t>::value;
static const bool is_general = !is_float && !is_vector && !is_context && !is_variadic;
static const u32 g_align = alignof32(T) > 4 ? alignof32(T) >> 2 : 1;
static const u32 g_value = is_general ? ((g_count + (g_align - 1)) & ~(g_align - 1)) + (g_align) : g_count;
static const u32 f_value = f_count + is_float;
static const u32 v_value = v_count + is_vector;
static const arg_class value =
is_general ? (g_value > 4 ? ARG_STACK : ARG_GENERAL) :
is_float ? (f_value > 9000 ? ARG_STACK : ARG_FLOAT) :
is_vector ? (v_value > 9000 ? ARG_STACK : ARG_VECTOR) :
is_context ? ARG_CONTEXT :
is_variadic ? ARG_VARIADIC :
ARG_UNKNOWN;
};
// wrapper for variadic argument info list, each value contains packed argument type and counts of GENERAL, FLOAT and VECTOR arguments
template<u32... Values> struct arg_info_pack_t;
template<u32 First, u32... Values> struct arg_info_pack_t<First, Values...>
{
static const u32 last_value = arg_info_pack_t<Values...>::last_value;
};
template<u32 First> struct arg_info_pack_t<First>
{
static const u32 last_value = First;
};
template<> struct arg_info_pack_t<>
{
static const u32 last_value = 0;
};
// argument type + g/f/v_count unpacker
template<typename T, u32 type_pack> struct bind_arg_packed
{
force_inline static T get_arg(ARMv7Context& context)
{
return bind_arg<T, static_cast<arg_class>(type_pack & 0xff), (type_pack >> 8) & 0xff, (type_pack >> 16) & 0xff, (type_pack >> 24)>::get_arg(context);
}
};
template<u32... Info, typename RT, typename... Args>
force_inline RT call(ARMv7Context& context, RT(*func)(Args...), arg_info_pack_t<Info...> info)
{
// do the actual function call when all arguments are prepared (simultaneous unpacking of Args... and Info...)
return func(bind_arg_packed<Args, Info>::get_arg(context)...);
}
template<typename T, typename... Types, u32... Info, typename RT, typename... Args>
force_inline RT call(ARMv7Context& context, RT(*func)(Args...), arg_info_pack_t<Info...> info)
{
// unpack previous type counts (0/0/0 for the first time)
const u32 g_count = (info.last_value >> 8) & 0xff;
const u32 f_count = (info.last_value >> 16) & 0xff;
const u32 v_count = (info.last_value >> 24);
using type = arg_type<T, g_count, f_count, v_count>;
const arg_class t = type::value;
const u32 g = type::g_value;
const u32 f = type::f_value;
const u32 v = type::v_value;
return call<Types...>(context, func, arg_info_pack_t<Info..., t | (g << 8) | (f << 16) | (v << 24)>{});
}
template<u32 g_count, u32 f_count, u32 v_count>
force_inline static bool put_func_args(ARMv7Context& context)
{
// terminator
return false;
}
template<u32 g_count, u32 f_count, u32 v_count, typename T1, typename... T>
force_inline static bool put_func_args(ARMv7Context& context, T1 arg, T... args)
{
using type = arg_type<T1, g_count, f_count, v_count>;
const arg_class t = type::value;
const u32 g = type::g_value;
const u32 f = type::f_value;
const u32 v = type::v_value;
bind_arg<T1, t, g, f, v>::put_arg(context, arg);
// return true if stack was used
return put_func_args<g, f, v>(context, args...) || (t == ARG_STACK);
}
template<typename RT, typename... T>
struct func_binder;
template<typename... T>
struct func_binder<void, T...>
{
using func_t = void(*)(T...);
static void do_call(ARMv7Context& context, func_t func)
{
call<T...>(context, func, arg_info_pack_t<>{});
}
};
template<typename RT, typename... T>
struct func_binder
{
using func_t = RT(*)(T...);
static void do_call(ARMv7Context& context, func_t func)
{
bind_result<RT, result_type<RT>::value>::put_result(context, call<T...>(context, func, arg_info_pack_t<>{}));
}
};
template<typename RT, typename... T>
struct func_caller
{
force_inline static RT call(ARMv7Context& context, u32 addr, T... args)
{
func_caller<void, T...>::call(context, addr, args...);
return bind_result<RT, result_type<RT>::value>::get_result(context);
}
};
template<typename... T>
struct func_caller<void, T...>
{
force_inline static void call(ARMv7Context& context, u32 addr, T... args)
{
if (put_func_args<0, 0, 0, T...>(context, args...))
{
context.SP -= FIXED_STACK_FRAME_SIZE;
context.fast_call(addr);
context.SP += FIXED_STACK_FRAME_SIZE;
}
else
{
context.fast_call(addr);
}
}
};
}
// Basic information about the HLE function
struct psv_func
{
u32 nid; // Unique function ID (should be generated individually for each elf loaded)
u32 flags;
const char* name; // Function name for information
armv7_func_caller func; // Function caller
psv_log_base* module; // Module for information
psv_func()
{
}
psv_func(u32 nid, u32 flags, psv_log_base* module, const char* name, armv7_func_caller func)
: nid(nid)
, flags(flags)
, name(name)
, func(func)
, module(module)
{
}
};
enum psv_special_function_index : u16
{
SFI_HLE_RETURN,
SFI_MAX
};
// Do not call directly
u32 add_psv_func(psv_func data);
// Do not call directly
template<typename RT, typename... T> force_inline void call_psv_func(ARMv7Context& context, RT(*func)(T...))
{
psv_func_detail::func_binder<RT, T...>::do_call(context, func);
}
#define reg_psv_func(nid, module, name, func) add_psv_func(psv_func(nid, 0, module, name, [](ARMv7Context& context){ call_psv_func(context, func); }))
// Find registered HLE function by NID
psv_func* get_psv_func_by_nid(u32 nid, u32* out_index = nullptr);
// Find registered HLE function by its index
psv_func* get_psv_func_by_index(u32 index);
// Execute registered HLE function by its index
void execute_psv_func_by_index(ARMv7Context& context, u32 index);
// Register all HLE functions
void initialize_psv_modules();
// Unregister all HLE functions
void finalize_psv_modules();
// General definitions
enum psv_error_codes
{
SCE_OK = 0,
SCE_ERROR_ERRNO_EPERM = 0x80010001,
SCE_ERROR_ERRNO_ENOENT = 0x80010002,
SCE_ERROR_ERRNO_ESRCH = 0x80010003,
SCE_ERROR_ERRNO_EINTR = 0x80010004,
SCE_ERROR_ERRNO_EIO = 0x80010005,
SCE_ERROR_ERRNO_ENXIO = 0x80010006,
SCE_ERROR_ERRNO_E2BIG = 0x80010007,
SCE_ERROR_ERRNO_ENOEXEC = 0x80010008,
SCE_ERROR_ERRNO_EBADF = 0x80010009,
SCE_ERROR_ERRNO_ECHILD = 0x8001000A,
SCE_ERROR_ERRNO_EAGAIN = 0x8001000B,
SCE_ERROR_ERRNO_ENOMEM = 0x8001000C,
SCE_ERROR_ERRNO_EACCES = 0x8001000D,
SCE_ERROR_ERRNO_EFAULT = 0x8001000E,
SCE_ERROR_ERRNO_ENOTBLK = 0x8001000F,
SCE_ERROR_ERRNO_EBUSY = 0x80010010,
SCE_ERROR_ERRNO_EEXIST = 0x80010011,
SCE_ERROR_ERRNO_EXDEV = 0x80010012,
SCE_ERROR_ERRNO_ENODEV = 0x80010013,
SCE_ERROR_ERRNO_ENOTDIR = 0x80010014,
SCE_ERROR_ERRNO_EISDIR = 0x80010015,
SCE_ERROR_ERRNO_EINVAL = 0x80010016,
SCE_ERROR_ERRNO_ENFILE = 0x80010017,
SCE_ERROR_ERRNO_EMFILE = 0x80010018,
SCE_ERROR_ERRNO_ENOTTY = 0x80010019,
SCE_ERROR_ERRNO_ETXTBSY = 0x8001001A,
SCE_ERROR_ERRNO_EFBIG = 0x8001001B,
SCE_ERROR_ERRNO_ENOSPC = 0x8001001C,
SCE_ERROR_ERRNO_ESPIPE = 0x8001001D,
SCE_ERROR_ERRNO_EROFS = 0x8001001E,
SCE_ERROR_ERRNO_EMLINK = 0x8001001F,
SCE_ERROR_ERRNO_EPIPE = 0x80010020,
SCE_ERROR_ERRNO_EDOM = 0x80010021,
SCE_ERROR_ERRNO_ERANGE = 0x80010022,
SCE_ERROR_ERRNO_ENOMSG = 0x80010023,
SCE_ERROR_ERRNO_EIDRM = 0x80010024,
SCE_ERROR_ERRNO_ECHRNG = 0x80010025,
SCE_ERROR_ERRNO_EL2NSYNC = 0x80010026,
SCE_ERROR_ERRNO_EL3HLT = 0x80010027,
SCE_ERROR_ERRNO_EL3RST = 0x80010028,
SCE_ERROR_ERRNO_ELNRNG = 0x80010029,
SCE_ERROR_ERRNO_EUNATCH = 0x8001002A,
SCE_ERROR_ERRNO_ENOCSI = 0x8001002B,
SCE_ERROR_ERRNO_EL2HLT = 0x8001002C,
SCE_ERROR_ERRNO_EDEADLK = 0x8001002D,
SCE_ERROR_ERRNO_ENOLCK = 0x8001002E,
SCE_ERROR_ERRNO_EFORMAT = 0x8001002F,
SCE_ERROR_ERRNO_EUNSUP = 0x80010030,
SCE_ERROR_ERRNO_EBADE = 0x80010032,
SCE_ERROR_ERRNO_EBADR = 0x80010033,
SCE_ERROR_ERRNO_EXFULL = 0x80010034,
SCE_ERROR_ERRNO_ENOANO = 0x80010035,
SCE_ERROR_ERRNO_EBADRQC = 0x80010036,
SCE_ERROR_ERRNO_EBADSLT = 0x80010037,
SCE_ERROR_ERRNO_EDEADLOCK = 0x80010038,
SCE_ERROR_ERRNO_EBFONT = 0x80010039,
SCE_ERROR_ERRNO_ENOSTR = 0x8001003C,
SCE_ERROR_ERRNO_ENODATA = 0x8001003D,
SCE_ERROR_ERRNO_ETIME = 0x8001003E,
SCE_ERROR_ERRNO_ENOSR = 0x8001003F,
SCE_ERROR_ERRNO_ENONET = 0x80010040,
SCE_ERROR_ERRNO_ENOPKG = 0x80010041,
SCE_ERROR_ERRNO_EREMOTE = 0x80010042,
SCE_ERROR_ERRNO_ENOLINK = 0x80010043,
SCE_ERROR_ERRNO_EADV = 0x80010044,
SCE_ERROR_ERRNO_ESRMNT = 0x80010045,
SCE_ERROR_ERRNO_ECOMM = 0x80010046,
SCE_ERROR_ERRNO_EPROTO = 0x80010047,
SCE_ERROR_ERRNO_EMULTIHOP = 0x8001004A,
SCE_ERROR_ERRNO_ELBIN = 0x8001004B,
SCE_ERROR_ERRNO_EDOTDOT = 0x8001004C,
SCE_ERROR_ERRNO_EBADMSG = 0x8001004D,
SCE_ERROR_ERRNO_EFTYPE = 0x8001004F,
SCE_ERROR_ERRNO_ENOTUNIQ = 0x80010050,
SCE_ERROR_ERRNO_EBADFD = 0x80010051,
SCE_ERROR_ERRNO_EREMCHG = 0x80010052,
SCE_ERROR_ERRNO_ELIBACC = 0x80010053,
SCE_ERROR_ERRNO_ELIBBAD = 0x80010054,
SCE_ERROR_ERRNO_ELIBSCN = 0x80010055,
SCE_ERROR_ERRNO_ELIBMAX = 0x80010056,
SCE_ERROR_ERRNO_ELIBEXEC = 0x80010057,
SCE_ERROR_ERRNO_ENOSYS = 0x80010058,
SCE_ERROR_ERRNO_ENMFILE = 0x80010059,
SCE_ERROR_ERRNO_ENOTEMPTY = 0x8001005A,
SCE_ERROR_ERRNO_ENAMETOOLONG = 0x8001005B,
SCE_ERROR_ERRNO_ELOOP = 0x8001005C,
SCE_ERROR_ERRNO_EOPNOTSUPP = 0x8001005F,
SCE_ERROR_ERRNO_EPFNOSUPPORT = 0x80010060,
SCE_ERROR_ERRNO_ECONNRESET = 0x80010068,
SCE_ERROR_ERRNO_ENOBUFS = 0x80010069,
SCE_ERROR_ERRNO_EAFNOSUPPORT = 0x8001006A,
SCE_ERROR_ERRNO_EPROTOTYPE = 0x8001006B,
SCE_ERROR_ERRNO_ENOTSOCK = 0x8001006C,
SCE_ERROR_ERRNO_ENOPROTOOPT = 0x8001006D,
SCE_ERROR_ERRNO_ESHUTDOWN = 0x8001006E,
SCE_ERROR_ERRNO_ECONNREFUSED = 0x8001006F,
SCE_ERROR_ERRNO_EADDRINUSE = 0x80010070,
SCE_ERROR_ERRNO_ECONNABORTED = 0x80010071,
SCE_ERROR_ERRNO_ENETUNREACH = 0x80010072,
SCE_ERROR_ERRNO_ENETDOWN = 0x80010073,
SCE_ERROR_ERRNO_ETIMEDOUT = 0x80010074,
SCE_ERROR_ERRNO_EHOSTDOWN = 0x80010075,
SCE_ERROR_ERRNO_EHOSTUNREACH = 0x80010076,
SCE_ERROR_ERRNO_EINPROGRESS = 0x80010077,
SCE_ERROR_ERRNO_EALREADY = 0x80010078,
SCE_ERROR_ERRNO_EDESTADDRREQ = 0x80010079,
SCE_ERROR_ERRNO_EMSGSIZE = 0x8001007A,
SCE_ERROR_ERRNO_EPROTONOSUPPORT = 0x8001007B,
SCE_ERROR_ERRNO_ESOCKTNOSUPPORT = 0x8001007C,
SCE_ERROR_ERRNO_EADDRNOTAVAIL = 0x8001007D,
SCE_ERROR_ERRNO_ENETRESET = 0x8001007E,
SCE_ERROR_ERRNO_EISCONN = 0x8001007F,
SCE_ERROR_ERRNO_ENOTCONN = 0x80010080,
SCE_ERROR_ERRNO_ETOOMANYREFS = 0x80010081,
SCE_ERROR_ERRNO_EPROCLIM = 0x80010082,
SCE_ERROR_ERRNO_EUSERS = 0x80010083,
SCE_ERROR_ERRNO_EDQUOT = 0x80010084,
SCE_ERROR_ERRNO_ESTALE = 0x80010085,
SCE_ERROR_ERRNO_ENOTSUP = 0x80010086,
SCE_ERROR_ERRNO_ENOMEDIUM = 0x80010087,
SCE_ERROR_ERRNO_ENOSHARE = 0x80010088,
SCE_ERROR_ERRNO_ECASECLASH = 0x80010089,
SCE_ERROR_ERRNO_EILSEQ = 0x8001008A,
SCE_ERROR_ERRNO_EOVERFLOW = 0x8001008B,
SCE_ERROR_ERRNO_ECANCELED = 0x8001008C,
SCE_ERROR_ERRNO_ENOTRECOVERABLE = 0x8001008D,
SCE_ERROR_ERRNO_EOWNERDEAD = 0x8001008E,
};
struct SceDateTime
{
le_t<u16> year;
le_t<u16> month;
le_t<u16> day;
le_t<u16> hour;
le_t<u16> minute;
le_t<u16> second;
le_t<u32> microsecond;
};
struct SceFVector3
{
le_t<float> x, y, z;
};
struct SceFQuaternion
{
le_t<float> x, y, z, w;
};
union SceUMatrix4
{
struct
{
le_t<float> f[4][4];
};
struct
{
le_t<s32> i[4][4];
};
};