some minor improvements

This commit is contained in:
InoriRus 2022-01-31 17:25:13 +10:00
parent 8651c18423
commit 9a912716f8
27 changed files with 1792 additions and 199 deletions

View file

@ -1,4 +1,4 @@
version: 0.0.7.build-{build}
version: 0.0.8.build-{build}
image: Visual Studio 2019
environment:
matrix:

View file

@ -82,7 +82,7 @@ if (KYTY_LINKER STREQUAL LD)
set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000")
endif()
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.7)
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.8)
include(src_script.cmake)

View file

@ -18,7 +18,10 @@ KYTY_SUBSYSTEM_DEFINE(Graphics);
void GraphicsDbgDumpDcb(const char* type, uint32_t num_dw, uint32_t* cmd_buffer);
int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier);
int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier);
int KYTY_SYSV_ABI GraphicsSetPsShader(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs);
int KYTY_SYSV_ABI GraphicsSetPsShader350(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs);
int KYTY_SYSV_ABI GraphicsUpdatePsShader(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs);
int KYTY_SYSV_ABI GraphicsSetCsShaderWithModifier(uint32_t* cmd, uint64_t size, const uint32_t* cs_regs, uint32_t shader_modifier);
int KYTY_SYSV_ABI GraphicsSetEmbeddedVsShader(uint32_t* cmd, uint64_t size, uint32_t id, uint32_t shader_modifier);
int KYTY_SYSV_ABI GraphicsDrawIndex(uint32_t* cmd, uint64_t size, uint32_t index_count, const void* index_addr, uint32_t flags,
@ -34,6 +37,9 @@ int KYTY_SYSV_ABI GraphicsAreSubmitsAllowed();
void KYTY_SYSV_ABI GraphicsFlushMemory();
int KYTY_SYSV_ABI GraphicsAddEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id, void* udata);
int KYTY_SYSV_ABI GraphicsDeleteEqEvent(LibKernel::EventQueue::KernelEqueue eq, int id);
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState(uint32_t* cmd, uint64_t size);
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState175(uint32_t* cmd, uint64_t size);
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState200(uint32_t* cmd, uint64_t size);
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState350(uint32_t* cmd, uint64_t size);
uint32_t KYTY_SYSV_ABI GraphicsDispatchInitDefaultHardwareState(uint32_t* cmd, uint64_t size);
int KYTY_SYSV_ABI GraphicsInsertWaitFlipDone(uint32_t* cmd, uint64_t size, uint32_t video_out_handle, uint32_t display_buffer_index);
@ -48,6 +54,7 @@ void KYTY_SYSV_ABI GraphicsUnmapComputeQueue(uint32_t id);
int KYTY_SYSV_ABI GraphicsInsertPushMarker(uint32_t* cmd, uint64_t size, const char* str);
int KYTY_SYSV_ABI GraphicsInsertPopMarker(uint32_t* cmd, uint64_t size);
uint64_t KYTY_SYSV_ABI GraphicsGetGpuCoreClockFrequency();
int KYTY_SYSV_ABI GraphicsIsUserPaEnabled();
int KYTY_SYSV_ABI GraphicsRegisterOwner(uint32_t* owner_handle, const char* name);
int KYTY_SYSV_ABI GraphicsRegisterResource(uint32_t* resource_handle, uint32_t owner_handle, const void* memory, size_t size,

View file

@ -182,6 +182,26 @@ struct BlendControl
bool enable = false;
};
struct BlendColor
{
float red = 0.0f;
float green = 0.0f;
float blue = 0.0f;
float alpha = 0.0f;
};
struct EqaaControl
{
uint8_t max_anchor_samples = 0;
uint8_t ps_iter_samples = 0;
uint8_t mask_export_num_samples = 0;
uint8_t alpha_to_mask_num_samples = 0;
bool high_quality_intersections = false;
bool incoherent_eqaa_reads = false;
bool interpolate_comp_z = false;
bool static_anchor_associations = false;
};
struct Viewport
{
float zmin = 0.0f;
@ -302,6 +322,8 @@ struct PixelShaderInfo
uint32_t ps_interpolator_settings[32] = {0};
uint32_t ps_input_num = 0;
UserSgprInfo ps_user_sgpr;
uint32_t ps_embedded_id = 0;
bool ps_embedded = false;
};
struct ComputeShaderInfo
@ -397,6 +419,8 @@ public:
m_cs.cs_shader_modifier = shader_modifier;
}
[[nodiscard]] const BlendColor& GetBlendColor() const { return m_blend_color; }
void SetBlendColor(const BlendColor& color) { m_blend_color = color; }
[[nodiscard]] const ClipControl& GetClipControl() const { return m_clip_control; }
void SetClipControl(const ClipControl& control) { m_clip_control = control; }
[[nodiscard]] const RenderControl& GetRenderControl() const { return m_render_control; }
@ -405,6 +429,8 @@ public:
void SetDepthControl(const DepthControl& control) { m_depth_control = control; }
[[nodiscard]] const ModeControl& GetModeControl() const { return m_mode_control; }
void SetModeControl(const ModeControl& control) { m_mode_control = control; }
[[nodiscard]] const EqaaControl& GetEqaaControl() const { return m_eqaa_control; }
void SetEqaaControl(const EqaaControl& control) { m_eqaa_control = control; }
void SetVsUserSgpr(uint32_t id, uint32_t value, UserSgprType type)
{
@ -439,6 +465,7 @@ public:
private:
BlendControl m_blend_control[8];
BlendColor m_blend_color;
RenderTarget m_render_targets[8];
uint32_t m_render_target_mask = 0;
ScreenViewport m_screen_viewport;
@ -455,6 +482,7 @@ private:
float m_depth_clear_value = 0.0f;
ModeControl m_mode_control;
EqaaControl m_eqaa_control;
};
class UserConfig

View file

@ -81,6 +81,9 @@ constexpr uint32_t R_DISPATCH_WAIT_MEM = 0x0A;
constexpr uint32_t R_PUSH_MARKER = 0x0B;
constexpr uint32_t R_POP_MARKER = 0x0C;
constexpr uint32_t R_VS_EMBEDDED = 0x0D;
constexpr uint32_t R_PS_EMBEDDED = 0x0E;
constexpr uint32_t R_VS_UPDATE = 0x0F;
constexpr uint32_t R_PS_UPDATE = 0x10;
constexpr uint32_t DB_RENDER_CONTROL = 0x0;
constexpr uint32_t DB_RENDER_CONTROL_DEPTH_CLEAR_ENABLE_SHIFT = 0;
@ -173,6 +176,11 @@ constexpr uint32_t DB_DEPTH_SLICE_SLICE_TILE_MAX_MASK = 0x3FFFFF;
constexpr uint32_t PA_SC_VPORT_ZMIN_0 = 0xB4;
constexpr uint32_t CB_BLEND_RED = 0x105;
constexpr uint32_t CB_BLEND_GREEN = 0x106;
constexpr uint32_t CB_BLEND_BLUE = 0x107;
constexpr uint32_t CB_BLEND_ALPHA = 0x108;
constexpr uint32_t PA_CL_VPORT_XSCALE = 0x10F;
constexpr uint32_t SPI_PS_INPUT_CNTL_0 = 0x191;
@ -213,6 +221,24 @@ constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_MASK = 0x7;
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_BF_SHIFT = 20;
constexpr uint32_t DB_DEPTH_CONTROL_STENCILFUNC_BF_MASK = 0x7;
constexpr uint32_t DB_EQAA = 0x201;
constexpr uint32_t DB_EQAA_MAX_ANCHOR_SAMPLES_SHIFT = 0;
constexpr uint32_t DB_EQAA_MAX_ANCHOR_SAMPLES_MASK = 0x7;
constexpr uint32_t DB_EQAA_PS_ITER_SAMPLES_SHIFT = 4;
constexpr uint32_t DB_EQAA_PS_ITER_SAMPLES_MASK = 0x7;
constexpr uint32_t DB_EQAA_MASK_EXPORT_NUM_SAMPLES_SHIFT = 8;
constexpr uint32_t DB_EQAA_MASK_EXPORT_NUM_SAMPLES_MASK = 0x7;
constexpr uint32_t DB_EQAA_ALPHA_TO_MASK_NUM_SAMPLES_SHIFT = 12;
constexpr uint32_t DB_EQAA_ALPHA_TO_MASK_NUM_SAMPLES_MASK = 0x7;
constexpr uint32_t DB_EQAA_HIGH_QUALITY_INTERSECTIONS_SHIFT = 16;
constexpr uint32_t DB_EQAA_HIGH_QUALITY_INTERSECTIONS_MASK = 0x1;
constexpr uint32_t DB_EQAA_INCOHERENT_EQAA_READS_SHIFT = 17;
constexpr uint32_t DB_EQAA_INCOHERENT_EQAA_READS_MASK = 0x1;
constexpr uint32_t DB_EQAA_INTERPOLATE_COMP_Z_SHIFT = 18;
constexpr uint32_t DB_EQAA_INTERPOLATE_COMP_Z_MASK = 0x1;
constexpr uint32_t DB_EQAA_STATIC_ANCHOR_ASSOCIATIONS_SHIFT = 20;
constexpr uint32_t DB_EQAA_STATIC_ANCHOR_ASSOCIATIONS_MASK = 0x1;
constexpr uint32_t PA_SU_SC_MODE_CNTL = 0x205;
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_FRONT_SHIFT = 0;
constexpr uint32_t PA_SU_SC_MODE_CNTL_CULL_FRONT_MASK = 0x1;

View file

@ -588,6 +588,7 @@ struct ShaderTextureResources
static constexpr int RES_MAX = 16;
ShaderTextureResource textures[RES_MAX];
int slots[RES_MAX] = {0};
int start_register[RES_MAX] = {0};
bool extended[RES_MAX] = {};
int textures_num = 0;
@ -599,6 +600,7 @@ struct ShaderSamplerResources
static constexpr int RES_MAX = 16;
ShaderSamplerResource samplers[RES_MAX];
int slots[RES_MAX] = {0};
int start_register[RES_MAX] = {0};
bool extended[RES_MAX] = {};
int samplers_num = 0;

View file

@ -20,6 +20,7 @@ int KYTY_SYSV_ABI KernelAllocateDirectMemory(int64_t search_start, int64_t se
int KYTY_SYSV_ABI KernelReleaseDirectMemory(int64_t start, size_t len);
int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int flags, int64_t direct_memory_start, size_t alignment);
int KYTY_SYSV_ABI KernelQueryMemoryProtection(void* addr, void** start, void** end, int* prot);
int KYTY_SYSV_ABI KernelDirectMemoryQuery(int64_t offset, int flags, void* info, size_t info_size);
} // namespace Kyty::Libs::LibKernel::Memory

View file

@ -18,7 +18,9 @@ namespace Kyty::Loader {
struct Program;
} // namespace Kyty::Loader
namespace Kyty::Libs::LibKernel {
namespace Kyty::Libs {
namespace LibKernel {
KYTY_SUBSYSTEM_DEFINE(Pthread);
@ -55,9 +57,11 @@ using KernelUseconds = unsigned int;
using PthreadCondattr = PthreadCondattrPrivate*;
using PthreadCond = PthreadCondPrivate*;
using KernelClockid = int32_t;
using PthreadKey = int;
using pthread_entry_func_t = KYTY_SYSV_ABI void* (*)(void*);
using thread_dtors_func_t = KYTY_SYSV_ABI void (*)();
using pthread_entry_func_t = KYTY_SYSV_ABI void* (*)(void*);
using thread_dtors_func_t = KYTY_SYSV_ABI void (*)();
using pthread_key_destructor_func_t = KYTY_SYSV_ABI void (*)(void*);
void PthreadInitSelfForMainThread();
void PthreadDeleteStaticObjects(Loader::Program* program);
@ -79,7 +83,10 @@ int KYTY_SYSV_ABI PthreadJoin(Pthread thread, void** value);
int KYTY_SYSV_ABI PthreadCancel(Pthread thread);
int KYTY_SYSV_ABI PthreadSetcancelstate(int state, int* old_state);
int KYTY_SYSV_ABI PthreadSetcanceltype(int type, int* old_type);
int KYTY_SYSV_ABI PthreadGetprio(Pthread thread, int* prio);
int KYTY_SYSV_ABI PthreadSetprio(Pthread thread, int prio);
void KYTY_SYSV_ABI PthreadTestcancel();
int KYTY_SYSV_ABI PthreadSetaffinity(Pthread thread, KernelCpumask mask);
void KYTY_SYSV_ABI PthreadExit(void* value);
int KYTY_SYSV_ABI PthreadEqual(Pthread thread1, Pthread thread2);
int KYTY_SYSV_ABI PthreadGetname(Pthread thread, char* name);
@ -87,6 +94,11 @@ int KYTY_SYSV_ABI KernelUsleep(KernelUseconds microseconds);
unsigned int KYTY_SYSV_ABI KernelSleep(unsigned int seconds);
int KYTY_SYSV_ABI KernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp);
int KYTY_SYSV_ABI PthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor);
int KYTY_SYSV_ABI PthreadKeyDelete(PthreadKey key);
int KYTY_SYSV_ABI PthreadSetspecific(PthreadKey key, void* value);
void* KYTY_SYSV_ABI PthreadGetspecific(PthreadKey key);
void KYTY_SYSV_ABI KernelSetThreadDtors(thread_dtors_func_t dtors);
int KYTY_SYSV_ABI PthreadAttrInit(PthreadAttr* attr);
@ -144,15 +156,26 @@ uint64_t KYTY_SYSV_ABI KernelGetProcessTime();
uint64_t KYTY_SYSV_ABI KernelGetProcessTimeCounter();
uint64_t KYTY_SYSV_ABI KernelGetProcessTimeCounterFrequency();
int KYTY_SYSV_ABI pthread_cond_broadcast_s(PthreadCond* cond);
int KYTY_SYSV_ABI pthread_cond_wait_s(PthreadCond* cond, PthreadMutex* mutex);
int KYTY_SYSV_ABI pthread_mutex_lock_s(PthreadMutex* mutex);
int KYTY_SYSV_ABI pthread_mutex_unlock_s(PthreadMutex* mutex);
int KYTY_SYSV_ABI pthread_rwlock_rdlock_s(PthreadRwlock* rwlock);
int KYTY_SYSV_ABI pthread_rwlock_unlock_s(PthreadRwlock* rwlock);
int KYTY_SYSV_ABI pthread_rwlock_wrlock_s(PthreadRwlock* rwlock);
} // namespace LibKernel
} // namespace Kyty::Libs::LibKernel
namespace Posix {
int KYTY_SYSV_ABI pthread_cond_broadcast(LibKernel::PthreadCond* cond);
int KYTY_SYSV_ABI pthread_cond_wait(LibKernel::PthreadCond* cond, LibKernel::PthreadMutex* mutex);
int KYTY_SYSV_ABI pthread_mutex_lock(LibKernel::PthreadMutex* mutex);
int KYTY_SYSV_ABI pthread_mutex_unlock(LibKernel::PthreadMutex* mutex);
int KYTY_SYSV_ABI pthread_rwlock_rdlock(LibKernel::PthreadRwlock* rwlock);
int KYTY_SYSV_ABI pthread_rwlock_unlock(LibKernel::PthreadRwlock* rwlock);
int KYTY_SYSV_ABI pthread_rwlock_wrlock(LibKernel::PthreadRwlock* rwlock);
int KYTY_SYSV_ABI pthread_key_create(LibKernel::PthreadKey* key, LibKernel::pthread_key_destructor_func_t destructor);
int KYTY_SYSV_ABI pthread_key_delete(LibKernel::PthreadKey key);
int KYTY_SYSV_ABI pthread_setspecific(LibKernel::PthreadKey key, void* value);
int KYTY_SYSV_ABI pthread_mutex_destroy(LibKernel::PthreadMutex* mutex);
int KYTY_SYSV_ABI pthread_mutex_init(LibKernel::PthreadMutex* mutex, const LibKernel::PthreadMutexattr* attr);
} // namespace Posix
} // namespace Kyty::Libs
#endif // KYTY_EMU_ENABLED

View file

@ -0,0 +1,28 @@
#ifndef EMULATOR_INCLUDE_EMULATOR_KERNEL_SEMAPHORE_H_
#define EMULATOR_INCLUDE_EMULATOR_KERNEL_SEMAPHORE_H_
#include "Kyty/Core/Common.h"
#include "Emulator/Common.h"
#include "Emulator/Kernel/Pthread.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::LibKernel::Semaphore {
class KernelSemaPrivate;
using KernelSema = KernelSemaPrivate*;
int KYTY_SYSV_ABI KernelCreateSema(KernelSema* sem, const char* name, uint32_t attr, int init, int max, void* opt);
int KYTY_SYSV_ABI KernelDeleteSema(KernelSema sem);
int KYTY_SYSV_ABI KernelWaitSema(KernelSema sem, int need, KernelUseconds* time);
int KYTY_SYSV_ABI KernelPollSema(KernelSema sem, int need);
int KYTY_SYSV_ABI KernelSignalSema(KernelSema sem, int count);
int KYTY_SYSV_ABI KernelCancelSema(KernelSema sem, int count, int* threads);
} // namespace Kyty::Libs::LibKernel::Semaphore
#endif // KYTY_EMU_ENABLED
#endif /* EMULATOR_INCLUDE_EMULATOR_KERNEL_SEMAPHORE_H_ */

View file

@ -7,7 +7,166 @@
constexpr int OK = 0;
namespace Kyty::Libs::LibKernel {
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define POSIX_CALL(func) \
[&]() \
{ \
auto result = func; \
if (result != OK) \
{ \
*GetErrorAddr() = LibKernel::KernelToPosix(result); \
return -1; \
} \
return 0; \
}()
// NOLINTNEXTLINE(cppcoreguidelines-macro-usage)
#define POSIX_PTHREAD_CALL(func) \
[&]() \
{ \
auto result = func; \
if (result != OK) \
{ \
return LibKernel::KernelToPosix(result); \
} \
return 0; \
}()
namespace Kyty::Libs {
namespace Posix {
KYTY_SYSV_ABI int* GetErrorAddr();
constexpr int POSIX_EPERM = 1;
constexpr int POSIX_ENOENT = 2;
constexpr int POSIX_ESRCH = 3;
constexpr int POSIX_EINTR = 4;
constexpr int POSIX_EIO = 5;
constexpr int POSIX_ENXIO = 6;
constexpr int POSIX_E2BIG = 7;
constexpr int POSIX_ENOEXEC = 8;
constexpr int POSIX_EBADF = 9;
constexpr int POSIX_ECHILD = 10;
constexpr int POSIX_EDEADLK = 11;
constexpr int POSIX_ENOMEM = 12;
constexpr int POSIX_EACCES = 13;
constexpr int POSIX_EFAULT = 14;
constexpr int POSIX_ENOTBLK = 15;
constexpr int POSIX_EBUSY = 16;
constexpr int POSIX_EEXIST = 17;
constexpr int POSIX_EXDEV = 18;
constexpr int POSIX_ENODEV = 19;
constexpr int POSIX_ENOTDIR = 20;
constexpr int POSIX_EISDIR = 21;
constexpr int POSIX_EINVAL = 22;
constexpr int POSIX_ENFILE = 23;
constexpr int POSIX_EMFILE = 24;
constexpr int POSIX_ENOTTY = 25;
constexpr int POSIX_ETXTBSY = 26;
constexpr int POSIX_EFBIG = 27;
constexpr int POSIX_ENOSPC = 28;
constexpr int POSIX_ESPIPE = 29;
constexpr int POSIX_EROFS = 30;
constexpr int POSIX_EMLINK = 31;
constexpr int POSIX_EPIPE = 32;
constexpr int POSIX_EDOM = 33;
constexpr int POSIX_ERANGE = 34;
constexpr int POSIX_EAGAIN = 35;
constexpr int POSIX_EWOULDBLOCK = 35;
constexpr int POSIX_EINPROGRESS = 36;
constexpr int POSIX_EALREADY = 37;
constexpr int POSIX_ENOTSOCK = 38;
constexpr int POSIX_EDESTADDRREQ = 39;
constexpr int POSIX_EMSGSIZE = 40;
constexpr int POSIX_EPROTOTYPE = 41;
constexpr int POSIX_ENOPROTOOPT = 42;
constexpr int POSIX_EPROTONOSUPPORT = 43;
constexpr int POSIX_ESOCKTNOSUPPORT = 44;
constexpr int POSIX_EOPNOTSUPP = 45;
constexpr int POSIX_ENOTSUP = 45;
constexpr int POSIX_EPFNOSUPPORT = 46;
constexpr int POSIX_EAFNOSUPPORT = 47;
constexpr int POSIX_EADDRINUSE = 48;
constexpr int POSIX_EADDRNOTAVAIL = 49;
constexpr int POSIX_ENETDOWN = 50;
constexpr int POSIX_ENETUNREACH = 51;
constexpr int POSIX_ENETRESET = 52;
constexpr int POSIX_ECONNABORTED = 53;
constexpr int POSIX_ECONNRESET = 54;
constexpr int POSIX_ENOBUFS = 55;
constexpr int POSIX_EISCONN = 56;
constexpr int POSIX_ENOTCONN = 57;
constexpr int POSIX_ESHUTDOWN = 58;
constexpr int POSIX_ETOOMANYREFS = 59;
constexpr int POSIX_ETIMEDOUT = 60;
constexpr int POSIX_ECONNREFUSED = 61;
constexpr int POSIX_ELOOP = 62;
constexpr int POSIX_ENAMETOOLONG = 63;
constexpr int POSIX_EHOSTDOWN = 64;
constexpr int POSIX_EHOSTUNREACH = 65;
constexpr int POSIX_ENOTEMPTY = 66;
constexpr int POSIX_EPROCLIM = 67;
constexpr int POSIX_EUSERS = 68;
constexpr int POSIX_EDQUOT = 69;
constexpr int POSIX_ESTALE = 70;
constexpr int POSIX_EREMOTE = 71;
constexpr int POSIX_EBADRPC = 72;
constexpr int POSIX_ERPCMISMATCH = 73;
constexpr int POSIX_EPROGUNAVAIL = 74;
constexpr int POSIX_EPROGMISMATCH = 75;
constexpr int POSIX_EPROCUNAVAIL = 76;
constexpr int POSIX_ENOLCK = 77;
constexpr int POSIX_ENOSYS = 78;
constexpr int POSIX_EFTYPE = 79;
constexpr int POSIX_EAUTH = 80;
constexpr int POSIX_ENEEDAUTH = 81;
constexpr int POSIX_EIDRM = 82;
constexpr int POSIX_ENOMSG = 83;
constexpr int POSIX_EOVERFLOW = 84;
constexpr int POSIX_ECANCELED = 85;
constexpr int POSIX_EILSEQ = 86;
constexpr int POSIX_ENOATTR = 87;
constexpr int POSIX_EDOOFUS = 88;
constexpr int POSIX_EBADMSG = 89;
constexpr int POSIX_EMULTIHOP = 90;
constexpr int POSIX_ENOLINK = 91;
constexpr int POSIX_EPROTO = 92;
constexpr int POSIX_ENOTCAPABLE = 93;
constexpr int POSIX_ECAPMODE = 94;
constexpr int POSIX_ENOBLK = 95;
constexpr int POSIX_EICV = 96;
constexpr int POSIX_ENOPLAYGOENT = 97;
constexpr int POSIX_EREVOKE = 98;
constexpr int POSIX_ESDKVERSION = 99;
constexpr int POSIX_ESTART = 100;
constexpr int POSIX_ESTOP = 101;
constexpr int POSIX_EINVALID2MB = 102;
constexpr int POSIX_ELAST = 102;
constexpr int POSIX_EADHOC = 160;
constexpr int POSIX_EINACTIVEDISABLED = 163;
constexpr int POSIX_ENETNODATA = 164;
constexpr int POSIX_ENETDESC = 165;
constexpr int POSIX_ENETDESCTIMEDOUT = 166;
constexpr int POSIX_ENETINTR = 167;
constexpr int POSIX_ERETURN = 205;
constexpr int POSIX_EFPOS = 152;
constexpr int POSIX_ENODATA = 1040;
constexpr int POSIX_ENOSR = 1050;
constexpr int POSIX_ENOSTR = 1051;
constexpr int POSIX_ENOTRECOVERABLE = 1056;
constexpr int POSIX_EOTHER = 1062;
constexpr int POSIX_EOWNERDEAD = 1064;
constexpr int POSIX_ETIME = 1074;
} // namespace Posix
namespace LibKernel {
inline int KernelToPosix(int kernel_errno)
{
return kernel_errno > -2147352576 && kernel_errno <= -2147352475 ? kernel_errno + 2147352576 : 1062;
}
constexpr int KERNEL_ERROR_UNKNOWN = -2147352576; /* 0x80020000 */
constexpr int KERNEL_ERROR_EPERM = -2147352575; /* 0x80020001 */
@ -114,9 +273,9 @@ constexpr int KERNEL_ERROR_ESDKVERSION = -2147352477; /* 0x80020063 */
constexpr int KERNEL_ERROR_ESTART = -2147352476; /* 0x80020064 */
constexpr int KERNEL_ERROR_ESTOP = -2147352475; /* 0x80020065 */
} // namespace Kyty::Libs::LibKernel
} // namespace LibKernel
namespace Kyty::Libs::VideoOut {
namespace VideoOut {
constexpr int VIDEO_OUT_ERROR_INVALID_VALUE = -2144796671; /* 0x80290001 */
constexpr int VIDEO_OUT_ERROR_INVALID_ADDRESS = -2144796670; /* 0x80290002 */
@ -148,7 +307,24 @@ constexpr int VIDEO_OUT_ERROR_FATAL = -2144796417; /*
constexpr int VIDEO_OUT_ERROR_UNKNOWN = -2144796418; /* 0x802900FE */
constexpr int VIDEO_OUT_ERROR_ENOMEM = -2144792564; /* 0x8029100C */
} // namespace Kyty::Libs::VideoOut
} // namespace VideoOut
namespace SystemService {
constexpr int SYSTEM_SERVICE_ERROR_INTERNAL = -2136932351; /* 0x80A10001 */
constexpr int SYSTEM_SERVICE_ERROR_UNAVAILABLE = -2136932350; /* 0x80A10002 */
constexpr int SYSTEM_SERVICE_ERROR_PARAMETER = -2136932349; /* 0x80A10003 */
constexpr int SYSTEM_SERVICE_ERROR_NO_EVENT = -2136932348; /* 0x80A10004 */
constexpr int SYSTEM_SERVICE_ERROR_REJECTED = -2136932347; /* 0x80A10005 */
constexpr int SYSTEM_SERVICE_ERROR_NEED_DISPLAY_SAFE_AREA_SETTINGS = -2136932346; /* 0x80A10006 */
constexpr int SYSTEM_SERVICE_ERROR_INVALID_URI_LEN = -2136932345; /* 0x80A10007 */
constexpr int SYSTEM_SERVICE_ERROR_INVALID_URI_SCHEME = -2136932344; /* 0x80A10008 */
constexpr int SYSTEM_SERVICE_ERROR_NO_APP_INFO = -2136932343; /* 0x80A10009 */
constexpr int SYSTEM_SERVICE_ERROR_NOT_FLAG_IN_PARAM_SFO = -2136932342; /* 0x80A1000A */
} // namespace SystemService
} // namespace Kyty::Libs
#endif // KYTY_EMU_ENABLED

View file

@ -69,6 +69,31 @@ int KYTY_SYSV_ABI GraphicsSetVsShader(uint32_t* cmd, uint64_t size, const VsStag
return OK;
}
int KYTY_SYSV_ABI GraphicsUpdateVsShader(uint32_t* cmd, uint64_t size, const VsStageRegisters* vs_regs, uint32_t shader_modifier)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(size < sizeof(VsStageRegisters) / 4 + 2);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
printf("\t shader_modifier = %" PRIu32 "\n", shader_modifier);
printf("\t vs_regs.m_spiShaderPgmLoVs = %08" PRIx32 "\n", vs_regs->m_spiShaderPgmLoVs);
printf("\t vs_regs.m_spiShaderPgmHiVs = %08" PRIx32 "\n", vs_regs->m_spiShaderPgmHiVs);
printf("\t vs_regs.m_spiShaderPgmRsrc1Vs = %08" PRIx32 "\n", vs_regs->m_spiShaderPgmRsrc1Vs);
printf("\t vs_regs.m_spiShaderPgmRsrc2Vs = %08" PRIx32 "\n", vs_regs->m_spiShaderPgmRsrc2Vs);
printf("\t vs_regs.m_spiVsOutConfig = %08" PRIx32 "\n", vs_regs->m_spiVsOutConfig);
printf("\t vs_regs.m_spiShaderPosFormat = %08" PRIx32 "\n", vs_regs->m_spiShaderPosFormat);
printf("\t vs_regs.m_paClVsOutCntl = %08" PRIx32 "\n", vs_regs->m_paClVsOutCntl);
cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_VS_UPDATE);
cmd[1] = shader_modifier;
memcpy(&cmd[2], vs_regs, sizeof(VsStageRegisters));
return OK;
}
int KYTY_SYSV_ABI GraphicsSetEmbeddedVsShader(uint32_t* cmd, uint64_t size, uint32_t id, uint32_t shader_modifier)
{
PRINT_NAME();
@ -87,12 +112,94 @@ int KYTY_SYSV_ABI GraphicsSetEmbeddedVsShader(uint32_t* cmd, uint64_t size, uint
return OK;
}
int KYTY_SYSV_ABI GraphicsSetPsShader(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs)
{
PRINT_NAME();
if (ps_regs == nullptr)
{
EXIT_NOT_IMPLEMENTED(size < 1 + 1);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
printf("\t embedded_id = %d\n", 0);
cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_PS_EMBEDDED);
cmd[1] = 0;
} else
{
EXIT_NOT_IMPLEMENTED(size < 12 + 1);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
printf("\t ps_regs.m_spiShaderPgmLoPs = %08" PRIx32 "\n", ps_regs[0]);
printf("\t ps_regs.m_spiShaderPgmHiPs = %08" PRIx32 "\n", ps_regs[1]);
printf("\t ps_regs.m_spiShaderPgmRsrc1Ps = %08" PRIx32 "\n", ps_regs[2]);
printf("\t ps_regs.m_spiShaderPgmRsrc2Ps = %08" PRIx32 "\n", ps_regs[3]);
printf("\t ps_regs.m_spiShaderZFormat = %08" PRIx32 "\n", ps_regs[4]);
printf("\t ps_regs.m_spiShaderColFormat = %08" PRIx32 "\n", ps_regs[5]);
printf("\t ps_regs.m_spiPsInputEna = %08" PRIx32 "\n", ps_regs[6]);
printf("\t ps_regs.m_spiPsInputAddr = %08" PRIx32 "\n", ps_regs[7]);
printf("\t ps_regs.m_spiPsInControl = %08" PRIx32 "\n", ps_regs[8]);
printf("\t ps_regs.m_spiBarycCntl = %08" PRIx32 "\n", ps_regs[9]);
printf("\t ps_regs.m_dbShaderControl = %08" PRIx32 "\n", ps_regs[10]);
printf("\t ps_regs.m_cbShaderMask = %08" PRIx32 "\n", ps_regs[11]);
cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_PS);
memcpy(&cmd[1], ps_regs, 12 * 4);
}
return OK;
}
int KYTY_SYSV_ABI GraphicsSetPsShader350(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs)
{
PRINT_NAME();
if (ps_regs == nullptr)
{
EXIT_NOT_IMPLEMENTED(size < 1 + 1);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
printf("\t embedded_id = %d\n", 0);
cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_PS_EMBEDDED);
cmd[1] = 0;
} else
{
EXIT_NOT_IMPLEMENTED(size < 12 + 1);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
printf("\t ps_regs.m_spiShaderPgmLoPs = %08" PRIx32 "\n", ps_regs[0]);
printf("\t ps_regs.m_spiShaderPgmHiPs = %08" PRIx32 "\n", ps_regs[1]);
printf("\t ps_regs.m_spiShaderPgmRsrc1Ps = %08" PRIx32 "\n", ps_regs[2]);
printf("\t ps_regs.m_spiShaderPgmRsrc2Ps = %08" PRIx32 "\n", ps_regs[3]);
printf("\t ps_regs.m_spiShaderZFormat = %08" PRIx32 "\n", ps_regs[4]);
printf("\t ps_regs.m_spiShaderColFormat = %08" PRIx32 "\n", ps_regs[5]);
printf("\t ps_regs.m_spiPsInputEna = %08" PRIx32 "\n", ps_regs[6]);
printf("\t ps_regs.m_spiPsInputAddr = %08" PRIx32 "\n", ps_regs[7]);
printf("\t ps_regs.m_spiPsInControl = %08" PRIx32 "\n", ps_regs[8]);
printf("\t ps_regs.m_spiBarycCntl = %08" PRIx32 "\n", ps_regs[9]);
printf("\t ps_regs.m_dbShaderControl = %08" PRIx32 "\n", ps_regs[10]);
printf("\t ps_regs.m_cbShaderMask = %08" PRIx32 "\n", ps_regs[11]);
cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_PS);
memcpy(&cmd[1], ps_regs, 12 * 4);
}
return OK;
}
int KYTY_SYSV_ABI GraphicsUpdatePsShader(uint32_t* cmd, uint64_t size, const uint32_t* ps_regs)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(ps_regs == nullptr);
EXIT_NOT_IMPLEMENTED(size < sizeof(PsStageRegisters) / 12 + 1);
EXIT_NOT_IMPLEMENTED(size < 12 + 1);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
@ -110,7 +217,7 @@ int KYTY_SYSV_ABI GraphicsSetPsShader350(uint32_t* cmd, uint64_t size, const uin
printf("\t ps_regs.m_dbShaderControl = %08" PRIx32 "\n", ps_regs[10]);
printf("\t ps_regs.m_cbShaderMask = %08" PRIx32 "\n", ps_regs[11]);
cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_PS);
cmd[0] = KYTY_PM4(size, Pm4::IT_NOP, Pm4::R_PS_UPDATE);
memcpy(&cmd[1], ps_regs, 12 * 4);
return OK;
@ -224,6 +331,48 @@ int KYTY_SYSV_ABI GraphicsDispatchDirect(uint32_t* cmd, uint64_t size, uint32_t
return OK;
}
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState(uint32_t* cmd, uint64_t size)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(size < 2);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
cmd[0] = KYTY_PM4(2, Pm4::IT_NOP, Pm4::R_DRAW_RESET);
return 2;
}
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState175(uint32_t* cmd, uint64_t size)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(size < 2);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
cmd[0] = KYTY_PM4(2, Pm4::IT_NOP, Pm4::R_DRAW_RESET);
return 2;
}
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState200(uint32_t* cmd, uint64_t size)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(size < 2);
printf("\t cmd_buffer = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(cmd));
printf("\t size = %" PRIu64 "\n", size);
cmd[0] = KYTY_PM4(2, Pm4::IT_NOP, Pm4::R_DRAW_RESET);
return 2;
}
uint32_t KYTY_SYSV_ABI GraphicsDrawInitDefaultHardwareState350(uint32_t* cmd, uint64_t size)
{
PRINT_NAME();
@ -464,6 +613,11 @@ uint64_t KYTY_SYSV_ABI GraphicsGetGpuCoreClockFrequency()
return LibKernel::KernelGetTscFrequency();
}
int KYTY_SYSV_ABI GraphicsIsUserPaEnabled()
{
return 0;
}
int KYTY_SYSV_ABI GraphicsRegisterOwner(uint32_t* owner_handle, const char* name)
{
PRINT_NAME();

View file

@ -70,6 +70,10 @@ struct PipelineParameters
uint8_t alpha_destblend = 0;
bool separate_alpha_blend = false;
bool blend_enable = false;
float blend_color_red = 0.0f;
float blend_color_green = 0.0f;
float blend_color_blue = 0.0f;
float blend_color_alpha = 0.0f;
bool operator==(const PipelineParameters& other) const;
};
@ -99,7 +103,8 @@ public:
VulkanPipeline* CreatePipeline(VulkanFramebuffer* framebuffer, RenderColorInfo* color, RenderDepthInfo* depth,
const ShaderVertexInputInfo* vs_input_info, const VertexShaderInfo* vs_regs,
const ShaderPixelInputInfo* ps_input_info, const PixelShaderInfo* ps_regs, VkPrimitiveTopology topology,
uint32_t color_mask, const ModeControl& mc, const BlendControl& bc, const ScreenViewport& vp);
uint32_t color_mask, const ModeControl& mc, const BlendControl& bc, const BlendColor& bclr,
const ScreenViewport& vp);
VulkanPipeline* CreatePipeline(const ShaderComputeInputInfo* input_info, const ComputeShaderInfo* cs_regs);
void DeletePipeline(VulkanPipeline* pipeline);
void DeletePipelines(VulkanFramebuffer* framebuffer);
@ -446,6 +451,7 @@ static void rt_check(const RenderTarget& rt)
{
if (rt.base_addr != 0)
{
bool render_to_texture = (rt.tile_mode == 0x0d);
// EXIT_NOT_IMPLEMENTED(rt.base_addr == 0);
// EXIT_NOT_IMPLEMENTED(rt.pitch_div8_minus1 != 0x000000ef);
// EXIT_NOT_IMPLEMENTED(rt.fmask_pitch_div8_minus1 != 0x000000ef);
@ -456,7 +462,7 @@ static void rt_check(const RenderTarget& rt)
EXIT_NOT_IMPLEMENTED(rt.fmask_compression_mode != 0x00000000);
EXIT_NOT_IMPLEMENTED(rt.cmask_fast_clear_enable != false);
EXIT_NOT_IMPLEMENTED(rt.dcc_compression_enable != false);
EXIT_NOT_IMPLEMENTED(rt.neo_mode != Config::IsNeo());
EXIT_NOT_IMPLEMENTED(!render_to_texture && rt.neo_mode != Config::IsNeo());
EXIT_NOT_IMPLEMENTED(rt.cmask_tile_mode != 0x00000000);
EXIT_NOT_IMPLEMENTED(rt.cmask_tile_mode_neo != 0x00000000);
// EXIT_NOT_IMPLEMENTED(rt.format != 0x0000000a);
@ -686,7 +692,7 @@ static void mc_check(const ModeControl& c)
EXIT_NOT_IMPLEMENTED(c.persp_corr_dis != false);
}
static void bc_print(const char* func, const BlendControl& c)
static void bc_print(const char* func, const BlendControl& c, const BlendColor& color)
{
printf("%s\n", func);
@ -698,9 +704,13 @@ static void bc_print(const char* func, const BlendControl& c)
printf("\t alpha_destblend = %" PRIu8 "\n", c.alpha_destblend);
printf("\t separate_alpha_blend = %s\n", c.separate_alpha_blend ? "true" : "false");
printf("\t enable = %s\n", c.enable ? "true" : "false");
printf("\t red = %f\n", color.red);
printf("\t green = %f\n", color.green);
printf("\t blue = %f\n", color.blue);
printf("\t alpha = %f\n", color.alpha);
}
static void bc_check(const BlendControl& c)
static void bc_check(const BlendControl& c, const BlendColor& color)
{
// EXIT_NOT_IMPLEMENTED(c.color_srcblend != 0);
EXIT_NOT_IMPLEMENTED(c.color_comb_fcn != 0);
@ -710,6 +720,10 @@ static void bc_check(const BlendControl& c)
EXIT_NOT_IMPLEMENTED(c.alpha_destblend != 0);
EXIT_NOT_IMPLEMENTED(c.separate_alpha_blend != false);
// EXIT_NOT_IMPLEMENTED(c.enable != false);
EXIT_NOT_IMPLEMENTED(color.red != 0.0f);
EXIT_NOT_IMPLEMENTED(color.green != 0.0f);
EXIT_NOT_IMPLEMENTED(color.blue != 0.0f);
EXIT_NOT_IMPLEMENTED(color.alpha != 0.0f);
}
static void d_print(const char* func, const DepthControl& c)
@ -738,6 +752,32 @@ static void d_check(const DepthControl& c)
EXIT_NOT_IMPLEMENTED(c.stencilfunc_bf != 0);
}
static void eqaa_print(const char* func, const EqaaControl& c)
{
printf("%s\n", func);
printf("\t max_anchor_samples = %" PRIu8 "\n", c.max_anchor_samples);
printf("\t ps_iter_samples = %" PRIu8 "\n", c.ps_iter_samples);
printf("\t mask_export_num_samples = %" PRIu8 "\n", c.mask_export_num_samples);
printf("\t alpha_to_mask_num_samples = %" PRIu8 "\n", c.alpha_to_mask_num_samples);
printf("\t high_quality_intersections = %s\n", c.high_quality_intersections ? "true" : "false");
printf("\t incoherent_eqaa_reads = %s\n", c.incoherent_eqaa_reads ? "true" : "false");
printf("\t interpolate_comp_z = %s\n", c.interpolate_comp_z ? "true" : "false");
printf("\t static_anchor_associations = %s\n", c.static_anchor_associations ? "true" : "false");
}
static void eqaa_check(const EqaaControl& c)
{
EXIT_NOT_IMPLEMENTED(c.max_anchor_samples != 0);
EXIT_NOT_IMPLEMENTED(c.ps_iter_samples != 0);
EXIT_NOT_IMPLEMENTED(c.mask_export_num_samples != 0);
EXIT_NOT_IMPLEMENTED(c.alpha_to_mask_num_samples != 0);
EXIT_NOT_IMPLEMENTED(c.high_quality_intersections != false);
EXIT_NOT_IMPLEMENTED(c.incoherent_eqaa_reads != false);
EXIT_NOT_IMPLEMENTED(c.interpolate_comp_z != false);
EXIT_NOT_IMPLEMENTED(c.static_anchor_associations != false);
}
static void vp_print(const char* func, const ScreenViewport& vp)
{
printf("%s\n", func);
@ -788,14 +828,16 @@ static void vp_check(const ScreenViewport& vp)
static void hw_check(const HardwareContext& hw)
{
const auto& rt = hw.GetRenderTargets(0);
const auto& bc = hw.GetBlendControl(0);
const auto& vp = hw.GetScreenViewport();
const auto& z = hw.GetDepthRenderTarget();
const auto& c = hw.GetClipControl();
const auto& rc = hw.GetRenderControl();
const auto& d = hw.GetDepthControl();
const auto& mc = hw.GetModeControl();
const auto& rt = hw.GetRenderTargets(0);
const auto& bc = hw.GetBlendControl(0);
const auto& bclr = hw.GetBlendColor();
const auto& vp = hw.GetScreenViewport();
const auto& z = hw.GetDepthRenderTarget();
const auto& c = hw.GetClipControl();
const auto& rc = hw.GetRenderControl();
const auto& d = hw.GetDepthControl();
const auto& mc = hw.GetModeControl();
const auto& eqaa = hw.GetEqaaControl();
rt_check(rt);
vp_check(vp);
@ -804,7 +846,8 @@ static void hw_check(const HardwareContext& hw)
rc_check(rc);
d_check(d);
mc_check(mc);
bc_check(bc);
bc_check(bc, bclr);
eqaa_check(eqaa);
EXIT_NOT_IMPLEMENTED(hw.GetRenderTargetMask() != 0xF && hw.GetRenderTargetMask() != 0x0);
EXIT_NOT_IMPLEMENTED(hw.GetDepthClearValue() != 0.0f && hw.GetDepthClearValue() != 1.0f);
@ -812,14 +855,16 @@ static void hw_check(const HardwareContext& hw)
static void hw_print(const HardwareContext& hw)
{
const auto& rt = hw.GetRenderTargets(0);
const auto& bc = hw.GetBlendControl(0);
const auto& vp = hw.GetScreenViewport();
const auto& z = hw.GetDepthRenderTarget();
const auto& c = hw.GetClipControl();
const auto& rc = hw.GetRenderControl();
const auto& d = hw.GetDepthControl();
const auto& mc = hw.GetModeControl();
const auto& rt = hw.GetRenderTargets(0);
const auto& bc = hw.GetBlendControl(0);
const auto& bclr = hw.GetBlendColor();
const auto& vp = hw.GetScreenViewport();
const auto& z = hw.GetDepthRenderTarget();
const auto& c = hw.GetClipControl();
const auto& rc = hw.GetRenderControl();
const auto& d = hw.GetDepthControl();
const auto& mc = hw.GetModeControl();
const auto& eqaa = hw.GetEqaaControl();
printf("HardwareContext\n");
printf("\t GetRenderTargetMask() = 0x%08" PRIx32 "\n", hw.GetRenderTargetMask());
@ -832,7 +877,8 @@ static void hw_print(const HardwareContext& hw)
rc_print("RenderControl:", rc);
d_print("DepthControl:", d);
mc_print("ModeControl:", mc);
bc_print("BlendControl:", bc);
bc_print("BlendControl:", bc, bclr);
eqaa_print("EqaaControl:", eqaa);
}
void GraphicsRenderInit()
@ -1749,10 +1795,10 @@ static VulkanPipeline* CreatePipelineInternal(VkRenderPass render_pass, const Sh
color_blending.logicOp = VK_LOGIC_OP_COPY;
color_blending.attachmentCount = 1;
color_blending.pAttachments = &color_blend_attachment;
color_blending.blendConstants[0] = 0.0f;
color_blending.blendConstants[1] = 0.0f;
color_blending.blendConstants[2] = 0.0f;
color_blending.blendConstants[3] = 0.0f;
color_blending.blendConstants[0] = params->blend_color_red;
color_blending.blendConstants[1] = params->blend_color_green;
color_blending.blendConstants[2] = params->blend_color_blue;
color_blending.blendConstants[3] = params->blend_color_alpha;
VkDescriptorSetLayout set_layouts[2] = {};
uint32_t set_layouts_num = 0;
@ -1957,7 +2003,7 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re
const ShaderVertexInputInfo* vs_input_info, const VertexShaderInfo* vs_regs,
const ShaderPixelInputInfo* ps_input_info, const PixelShaderInfo* ps_regs,
VkPrimitiveTopology topology, uint32_t color_mask, const ModeControl& mc,
const BlendControl& bc, const ScreenViewport& vp)
const BlendControl& bc, const BlendColor& bclr, const ScreenViewport& vp)
{
KYTY_PROFILER_BLOCK("PipelineCache::CreatePipeline(Gfx)", profiler::colors::DeepOrangeA200);
@ -2012,6 +2058,10 @@ VulkanPipeline* PipelineCache::CreatePipeline(VulkanFramebuffer* framebuffer, Re
p.params->alpha_destblend = bc.alpha_destblend;
p.params->separate_alpha_blend = bc.separate_alpha_blend;
p.params->blend_enable = bc.enable;
p.params->blend_color_red = bclr.red;
p.params->blend_color_green = bclr.green;
p.params->blend_color_blue = bclr.blue;
p.params->blend_color_alpha = bclr.alpha;
auto* found = Find(p);
@ -2869,12 +2919,13 @@ static void FindRenderColorInfo(const HardwareContext& hw, RenderColorInfo* r)
if (rt.base_addr != 0)
{
auto width = rt.width;
auto height = rt.height;
auto pitch = (rt.pitch_div8_minus1 + 1) * 8;
auto size = (rt.slice_div64_minus1 + 1) * 64 * 4;
bool tile = false;
uint32_t format = 0;
auto width = rt.width;
auto height = rt.height;
auto pitch = (rt.pitch_div8_minus1 + 1) * 8;
auto size = (rt.slice_div64_minus1 + 1) * 64 * 4;
bool tile = false;
uint32_t format = 0;
bool render_to_texture = false;
if (rt.tile_mode == 0x8)
{
@ -2882,38 +2933,48 @@ static void FindRenderColorInfo(const HardwareContext& hw, RenderColorInfo* r)
} else if (rt.tile_mode == 0xa)
{
tile = true;
} else if (rt.tile_mode == 0xd)
{
tile = true;
render_to_texture = true;
} else
{
EXIT("unknown tile mode: %u\n", rt.tile_mode);
}
if (rt.format == 0xa && rt.channel_type == 0x6 && rt.channel_order == 0x1)
if (render_to_texture)
{
format = 0x80000000;
EXIT("not implemented");
} else
{
EXIT("unknown format");
}
if (rt.format == 0xa && rt.channel_type == 0x6 && rt.channel_order == 0x1)
{
format = 0x80000000;
} else
{
EXIT("unknown format");
}
auto video_image = VideoOut::VideoOutGetImage(rt.base_addr);
if (video_image.image == nullptr)
{
// Offscreen buffer
VideoOutBufferObject vulkan_buffer_info(format, width, height, tile, Config::IsNeo(), pitch);
auto* buffer_vulkan = static_cast<Graphics::VideoOutVulkanImage*>(
Graphics::GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), rt.base_addr, size, vulkan_buffer_info));
EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr);
r->base_addr = rt.base_addr;
r->vulkan_buffer = buffer_vulkan;
r->buffer_size = size;
} else
{
// Display buffer
EXIT_NOT_IMPLEMENTED(video_image.buffer_size != size);
EXIT_NOT_IMPLEMENTED(video_image.buffer_pitch != pitch);
r->base_addr = rt.base_addr;
r->vulkan_buffer = video_image.image;
r->buffer_size = video_image.buffer_size;
auto video_image = VideoOut::VideoOutGetImage(rt.base_addr);
if (video_image.image == nullptr)
{
// Offscreen buffer
VideoOutBufferObject vulkan_buffer_info(format, width, height, tile, Config::IsNeo(), pitch);
auto* buffer_vulkan = static_cast<Graphics::VideoOutVulkanImage*>(
Graphics::GpuMemoryGetObject(g_render_ctx->GetGraphicCtx(), rt.base_addr, size, vulkan_buffer_info));
EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr);
r->base_addr = rt.base_addr;
r->vulkan_buffer = buffer_vulkan;
r->buffer_size = size;
} else
{
// Display buffer
EXIT_NOT_IMPLEMENTED(video_image.buffer_size != size);
EXIT_NOT_IMPLEMENTED(video_image.buffer_pitch != pitch);
r->base_addr = rt.base_addr;
r->vulkan_buffer = video_image.image;
r->buffer_size = video_image.buffer_size;
}
}
} else
{
@ -3269,9 +3330,10 @@ void GraphicsRenderDrawIndex(CommandBuffer* buffer, HardwareContext* ctx, UserCo
EXIT_NOT_IMPLEMENTED(vs_input_info.buffers_num > 1);
auto* pipeline = g_render_ctx->GetPipelineCache()->CreatePipeline(
framebuffer, &color_info, &depth_info, &vs_input_info, &ctx->GetVs(), &ps_input_info, &ctx->GetPs(),
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, ctx->GetRenderTargetMask(), ctx->GetModeControl(), bc, ctx->GetScreenViewport());
auto* pipeline = g_render_ctx->GetPipelineCache()->CreatePipeline(framebuffer, &color_info, &depth_info, &vs_input_info, &ctx->GetVs(),
&ps_input_info, &ctx->GetPs(), VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
ctx->GetRenderTargetMask(), ctx->GetModeControl(), bc,
ctx->GetBlendColor(), ctx->GetScreenViewport());
vkCmdBindPipeline(vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
@ -3376,7 +3438,7 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HardwareContext* ctx, Us
auto* pipeline = g_render_ctx->GetPipelineCache()->CreatePipeline(
framebuffer, &color_info, &depth_info, &vs_input_info, &vertex_shader_info, &ps_input_info, &pixel_shader_info, topology,
ctx->GetRenderTargetMask(), ctx->GetModeControl(), bc, ctx->GetScreenViewport());
ctx->GetRenderTargetMask(), ctx->GetModeControl(), bc, ctx->GetBlendColor(), ctx->GetScreenViewport());
vkCmdBindPipeline(vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);

View file

@ -1455,6 +1455,27 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_depth_control)
return 1;
}
KYTY_HW_CTX_PARSER(hw_ctx_set_eqaa_control)
{
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900);
EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::DB_EQAA);
EqaaControl r;
r.max_anchor_samples = KYTY_PM4_GET(buffer[0], DB_EQAA, MAX_ANCHOR_SAMPLES);
r.ps_iter_samples = KYTY_PM4_GET(buffer[0], DB_EQAA, PS_ITER_SAMPLES);
r.mask_export_num_samples = KYTY_PM4_GET(buffer[0], DB_EQAA, MASK_EXPORT_NUM_SAMPLES);
r.alpha_to_mask_num_samples = KYTY_PM4_GET(buffer[0], DB_EQAA, ALPHA_TO_MASK_NUM_SAMPLES);
r.high_quality_intersections = KYTY_PM4_GET(buffer[0], DB_EQAA, HIGH_QUALITY_INTERSECTIONS) != 0;
r.incoherent_eqaa_reads = KYTY_PM4_GET(buffer[0], DB_EQAA, INCOHERENT_EQAA_READS) != 0;
r.interpolate_comp_z = KYTY_PM4_GET(buffer[0], DB_EQAA, INTERPOLATE_COMP_Z) != 0;
r.static_anchor_associations = KYTY_PM4_GET(buffer[0], DB_EQAA, STATIC_ANCHOR_ASSOCIATIONS) != 0;
cp->GetCtx()->SetEqaaControl(r);
return 1;
}
KYTY_HW_CTX_PARSER(hw_ctx_set_depth_clear)
{
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC0016900);
@ -1671,6 +1692,23 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_guard_bands)
return 4;
}
KYTY_HW_CTX_PARSER(hw_ctx_set_blend_color)
{
EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0046900);
EXIT_NOT_IMPLEMENTED(cmd_offset != Pm4::CB_BLEND_RED);
BlendColor r;
r.red = *reinterpret_cast<const float*>(&buffer[0]);
r.green = *reinterpret_cast<const float*>(&buffer[1]);
r.blue = *reinterpret_cast<const float*>(&buffer[2]);
r.alpha = *reinterpret_cast<const float*>(&buffer[3]);
cp->GetCtx()->SetBlendColor(r);
return 4;
}
KYTY_HW_CTX_PARSER(hw_ctx_set_vs_shader)
{
EXIT_NOT_IMPLEMENTED(cmd_id != 0xC01B1004);
@ -2350,8 +2388,10 @@ static void graphics_init_jmp_tables()
g_hw_ctx_func[Pm4::DB_STENCIL_INFO] = hw_ctx_set_stencil_info;
g_hw_ctx_func[0x08d] = hw_ctx_hardware_screen_offset;
g_hw_ctx_func[0x08e] = hw_ctx_set_render_target_mask;
g_hw_ctx_func[Pm4::CB_BLEND_RED] = hw_ctx_set_blend_color;
g_hw_ctx_func[Pm4::SPI_PS_INPUT_CNTL_0] = hw_ctx_set_ps_input;
g_hw_ctx_func[Pm4::DB_DEPTH_CONTROL] = hw_ctx_set_depth_control;
g_hw_ctx_func[Pm4::DB_EQAA] = hw_ctx_set_eqaa_control;
g_hw_ctx_func[0x204] = hw_ctx_set_clip_control;
g_hw_ctx_func[Pm4::PA_SU_SC_MODE_CNTL] = hw_ctx_set_mode_control;
g_hw_ctx_func[0x206] = hw_ctx_set_viewport_transform_control;

View file

@ -39,6 +39,9 @@ static void init_names()
g_r_names[R_PUSH_MARKER] = "R_PUSH_MARKER";
g_r_names[R_POP_MARKER] = "R_POP_MARKER";
g_r_names[R_VS_EMBEDDED] = "R_VS_EMBEDDED";
g_r_names[R_PS_EMBEDDED] = "R_PS_EMBEDDED";
g_r_names[R_VS_UPDATE] = "R_VS_UPDATE";
g_r_names[R_PS_UPDATE] = "R_PS_UPDATE";
g_names[IT_NOP] = "IT_NOP";
g_names[IT_SET_BASE] = "IT_SET_BASE";

View file

@ -2205,7 +2205,7 @@ static void ShaderGetTextureBuffer(ShaderTextureResources* info, int start_index
EXIT_IF(info == nullptr);
EXIT_NOT_IMPLEMENTED(info->textures_num < 0 || info->textures_num >= ShaderTextureResources::RES_MAX);
EXIT_NOT_IMPLEMENTED(info->textures_num != slot);
// EXIT_NOT_IMPLEMENTED(info->textures_num != slot);
int index = info->textures_num;
bool extended = (extended_buffer != nullptr);
@ -2215,6 +2215,7 @@ static void ShaderGetTextureBuffer(ShaderTextureResources* info, int start_index
info->start_register[index] = start_index;
info->extended[index] = extended;
info->slots[index] = slot;
if (!extended)
{
@ -2243,7 +2244,7 @@ static void ShaderGetSampler(ShaderSamplerResources* info, int start_index, int
EXIT_IF(info == nullptr);
EXIT_NOT_IMPLEMENTED(info->samplers_num < 0 || info->samplers_num >= ShaderSamplerResources::RES_MAX);
EXIT_NOT_IMPLEMENTED(info->samplers_num != slot);
// EXIT_NOT_IMPLEMENTED(info->samplers_num != slot);
int index = info->samplers_num;
bool extended = (extended_buffer != nullptr);
@ -2253,6 +2254,7 @@ static void ShaderGetSampler(ShaderSamplerResources* info, int start_index, int
info->start_register[index] = start_index;
info->extended[index] = extended;
info->slots[index] = slot;
if (!extended)
{
@ -2277,7 +2279,7 @@ static void ShaderGetGdsPointer(ShaderGdsResources* info, int start_index, int s
EXIT_IF(info == nullptr);
EXIT_NOT_IMPLEMENTED(info->pointers_num < 0 || info->pointers_num >= ShaderGdsResources::POINTERS_MAX);
EXIT_NOT_IMPLEMENTED(info->pointers_num != slot);
// EXIT_NOT_IMPLEMENTED(info->pointers_num != slot);
int index = info->pointers_num;
bool extended = (extended_buffer != nullptr);
@ -2287,6 +2289,7 @@ static void ShaderGetGdsPointer(ShaderGdsResources* info, int start_index, int s
info->start_register[index] = start_index;
info->extended[index] = extended;
info->slots[index] = slot;
if (!extended)
{
@ -2514,9 +2517,16 @@ void ShaderGetInputInfoCS(const ComputeShaderInfo* regs, ShaderComputeInputInfo*
switch (usage.type)
{
case 0x00:
EXIT_NOT_IMPLEMENTED(usage.flags != 0);
ShaderGetStorageBuffer(&info->bind.storage_buffers, usage.start_register, usage.slot, ShaderStorageUsage::ReadOnly,
regs->cs_user_sgpr, extended_buffer);
EXIT_NOT_IMPLEMENTED(usage.flags != 0 && usage.flags != 3);
if (usage.flags == 0)
{
ShaderGetStorageBuffer(&info->bind.storage_buffers, usage.start_register, usage.slot, ShaderStorageUsage::ReadOnly,
regs->cs_user_sgpr, extended_buffer);
} else if (usage.flags == 3)
{
ShaderGetTextureBuffer(&info->bind.textures2D, usage.start_register, usage.slot, regs->cs_user_sgpr, extended_buffer);
EXIT_NOT_IMPLEMENTED(info->bind.textures2D.textures[info->bind.textures2D.textures_num - 1].Type() != 9);
}
break;
case 0x02:
EXIT_NOT_IMPLEMENTED(usage.flags != 0);
@ -2627,6 +2637,7 @@ static void ShaderDbgDumpResources(const ShaderBindResources& bind)
printf("\t\t MinLodWarn() = %" PRIu16 "\n", r.MinLodWarn());
printf("\t\t CounterBankId() = %" PRIu8 "\n", r.CounterBankId());
printf("\t\t LodHdwCntEn() = %s\n", r.LodHdwCntEn() ? "true" : "false");
printf("\t\t slot = %d\n", bind.textures2D.slots[i]);
printf("\t\t start_register = %d\n", bind.textures2D.start_register[i]);
printf("\t\t extended = %s\n", (bind.textures2D.extended[i] ? "true" : "false"));
}
@ -2664,6 +2675,7 @@ static void ShaderDbgDumpResources(const ShaderBindResources& bind)
printf("\t\t MipFilter() = %" PRIu8 "\n", r.MipFilter());
printf("\t\t BorderColorPtr() = %" PRIu16 "\n", r.BorderColorPtr());
printf("\t\t BorderColorType() = %" PRIu8 "\n", r.BorderColorType());
printf("\t\t slot = %d\n", bind.samplers.slots[i]);
printf("\t\t start_register = %d\n", bind.samplers.start_register[i]);
printf("\t\t extended = %s\n", (bind.samplers.extended[i] ? "true" : "false"));
}
@ -3208,6 +3220,7 @@ static void ShaderGetBindIds(ShaderId* ret, const ShaderBindResources& bind)
ret->ids.Add(r.MinLodWarn());
ret->ids.Add(r.CounterBankId());
ret->ids.Add(static_cast<uint32_t>(r.LodHdwCntEn()));
ret->ids.Add(bind.textures2D.slots[i]);
ret->ids.Add(bind.textures2D.start_register[i]);
ret->ids.Add(static_cast<uint32_t>(bind.textures2D.extended[i]));
}
@ -3243,6 +3256,7 @@ static void ShaderGetBindIds(ShaderId* ret, const ShaderBindResources& bind)
ret->ids.Add(r.MipFilter());
ret->ids.Add(r.BorderColorPtr());
ret->ids.Add(r.BorderColorType());
ret->ids.Add(bind.samplers.slots[i]);
ret->ids.Add(bind.samplers.start_register[i]);
ret->ids.Add(static_cast<uint32_t>(bind.samplers.extended[i]));
}

View file

@ -35,6 +35,7 @@ public:
int prot;
VirtualMemory::Mode mode;
Graphics::GpuMemoryMode gpu_mode;
int memory_type;
};
PhysicalMemory() { EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); }
@ -44,11 +45,12 @@ public:
static uint64_t Size() { return static_cast<uint64_t>(5376) * 1024 * 1024; }
bool Alloc(uint64_t search_start, uint64_t search_end, size_t len, size_t alignment, uint64_t* phys_addr_out);
bool Alloc(uint64_t search_start, uint64_t search_end, size_t len, size_t alignment, uint64_t* phys_addr_out, int memory_type);
bool Release(uint64_t start, size_t len, uint64_t* vaddr, uint64_t* size, Graphics::GpuMemoryMode* gpu_mode);
bool Map(uint64_t vaddr, uint64_t phys_addr, size_t len, int prot, VirtualMemory::Mode mode, Graphics::GpuMemoryMode gpu_mode);
bool Unmap(uint64_t vaddr, uint64_t size, Graphics::GpuMemoryMode* gpu_mode);
bool Find(uint64_t vaddr, uint64_t* base_addr, size_t* len, int* prot, VirtualMemory::Mode* mode, Graphics::GpuMemoryMode* gpu_mode);
bool Find(uint64_t phys_addr, bool next, PhysicalMemory::AllocatedBlock* out);
private:
Vector<AllocatedBlock> m_allocated;
@ -99,7 +101,8 @@ static uint64_t get_aligned_pos(uint64_t pos, size_t align)
return (align != 0 ? (pos + (align - 1)) & ~(align - 1) : pos);
}
bool PhysicalMemory::Alloc(uint64_t search_start, uint64_t search_end, size_t len, size_t alignment, uint64_t* phys_addr_out)
bool PhysicalMemory::Alloc(uint64_t search_start, uint64_t search_end, size_t len, size_t alignment, uint64_t* phys_addr_out,
int memory_type)
{
if (phys_addr_out == nullptr)
{
@ -124,13 +127,14 @@ bool PhysicalMemory::Alloc(uint64_t search_start, uint64_t search_end, size_t le
if (free_pos >= search_start && free_pos + len <= search_end)
{
AllocatedBlock b {};
b.size = len;
b.start_addr = free_pos;
b.gpu_mode = Graphics::GpuMemoryMode::NoAccess;
b.map_size = 0;
b.map_vaddr = 0;
b.prot = 0;
b.mode = VirtualMemory::Mode::NoAccess;
b.size = len;
b.start_addr = free_pos;
b.gpu_mode = Graphics::GpuMemoryMode::NoAccess;
b.map_size = 0;
b.map_vaddr = 0;
b.prot = 0;
b.mode = VirtualMemory::Mode::NoAccess;
b.memory_type = memory_type;
m_allocated.Add(b);
@ -219,6 +223,43 @@ bool PhysicalMemory::Unmap(uint64_t vaddr, uint64_t size, Graphics::GpuMemoryMod
return false;
}
bool PhysicalMemory::Find(uint64_t phys_addr, bool next, AllocatedBlock* out)
{
EXIT_IF(out == nullptr);
Core::LockGuard lock(m_mutex);
for (auto& b: m_allocated)
{
if (phys_addr >= b.start_addr && phys_addr < b.start_addr + b.size)
{
*out = b;
return true;
}
}
if (next)
{
uint64_t min_start_addr = UINT64_MAX;
AllocatedBlock* next = nullptr;
for (auto& b: m_allocated)
{
if (b.start_addr > phys_addr && b.start_addr < min_start_addr)
{
min_start_addr = b.start_addr;
next = &b;
}
}
if (next != nullptr)
{
*out = *next;
return true;
}
}
return false;
}
bool PhysicalMemory::Find(uint64_t vaddr, uint64_t* base_addr, size_t* len, int* prot, VirtualMemory::Mode* mode,
Graphics::GpuMemoryMode* gpu_mode)
{
@ -428,6 +469,49 @@ size_t KYTY_SYSV_ABI KernelGetDirectMemorySize()
return PhysicalMemory::Size();
}
int KYTY_SYSV_ABI KernelDirectMemoryQuery(int64_t offset, int flags, void* info, size_t info_size)
{
PRINT_NAME();
EXIT_IF(g_physical_memory == nullptr);
printf("\t offset = 0x%016" PRIx64 "\n", offset);
printf("\t flags = 0x%08" PRIx32 "\n", flags);
printf("\t info_size = 0x%016" PRIx64 "\n", info_size);
struct QueryInfo
{
int64_t start;
int64_t end;
int memory_type;
};
if (offset < 0 || info_size != sizeof(QueryInfo) || info == nullptr)
{
return KERNEL_ERROR_EINVAL;
}
PhysicalMemory::AllocatedBlock block {};
if (!g_physical_memory->Find(offset, flags != 0, &block))
{
printf(FG_RED "\t[Fail]\n" FG_DEFAULT);
return KERNEL_ERROR_EACCES;
}
auto* query_info = static_cast<QueryInfo*>(info);
query_info->start = static_cast<int64_t>(block.start_addr);
query_info->end = static_cast<int64_t>(block.start_addr + block.size);
query_info->memory_type = block.memory_type;
printf("\t start = %016" PRIx64 "\n", query_info->start);
printf("\t end = %016" PRIx64 "\n", query_info->end);
printf("\t memory_type = %d\n", query_info->memory_type);
printf(FG_GREEN "\t[Ok]\n" FG_DEFAULT);
return OK;
}
int KYTY_SYSV_ABI KernelAllocateDirectMemory(int64_t search_start, int64_t search_end, size_t len, size_t alignment, int memory_type,
int64_t* phys_addr_out)
{
@ -447,7 +531,7 @@ int KYTY_SYSV_ABI KernelAllocateDirectMemory(int64_t search_start, int64_t searc
}
uint64_t addr = 0;
if (!g_physical_memory->Alloc(search_start, search_end, len, alignment, &addr))
if (!g_physical_memory->Alloc(search_start, search_end, len, alignment, &addr, memory_type))
{
printf(FG_RED "\t[Fail]\n" FG_DEFAULT);
return KERNEL_ERROR_EAGAIN;

View file

@ -23,10 +23,15 @@
#include <pthread.h>
#include <pthread_time.h>
namespace Kyty::Libs::LibKernel {
namespace Kyty::Libs {
namespace LibKernel {
LIB_NAME("libkernel", "libkernel");
constexpr int KEYS_MAX = 256;
constexpr int DESTRUCTOR_ITERATIONS = 4;
struct PthreadMutexPrivate
{
uint8_t reserved[256];
@ -123,6 +128,38 @@ private:
Core::Mutex m_mutex;
};
class PthreadKeys
{
public:
PthreadKeys() { EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); }
virtual ~PthreadKeys() { KYTY_NOT_IMPLEMENTED; }
KYTY_CLASS_NO_COPY(PthreadKeys);
bool Create(int* key, pthread_key_destructor_func_t destructor);
bool Delete(int key);
void Destruct(int thread_id);
bool Set(int key, int thread_id, void* data);
bool Get(int key, int thread_id, void** data);
private:
struct Map
{
int thread_id = -1;
void* data = nullptr;
};
struct Key
{
bool used = false;
pthread_key_destructor_func_t destructor = nullptr;
Vector<Map> specific_values;
};
Core::Mutex m_mutex;
Key m_keys[KEYS_MAX];
};
class PthreadPool
{
public:
@ -160,18 +197,21 @@ public:
void SetPthreadPool(PthreadPool* pool) { m_pthread_pool = pool; }
PthreadStaticObjects* GetPthreadStaticObjects() { return m_pthread_static_objects; }
void SetPthreadStaticObjects(PthreadStaticObjects* objs) { m_pthread_static_objects = objs; }
PthreadKeys* GetPthreadKeys() { return m_pthread_keys; }
void SetPthreadKeys(PthreadKeys* keys) { m_pthread_keys = keys; }
[[nodiscard]] thread_dtors_func_t GetThreadDtors() const { return m_thread_dtors; }
void SetThreadDtors(thread_dtors_func_t dtors) { m_thread_dtors = dtors; }
private:
Core::Mutex m_mutex;
// Core::Mutex m_mutex;
PthreadMutexattr m_default_mutexattr = nullptr;
PthreadRwlockattr m_default_rwlockattr = nullptr;
PthreadCondattr m_default_condattr = nullptr;
PthreadAttr m_default_attr = nullptr;
PthreadPool* m_pthread_pool = nullptr;
PthreadStaticObjects* m_pthread_static_objects = nullptr;
PthreadKeys* m_pthread_keys = nullptr;
std::atomic<thread_dtors_func_t> m_thread_dtors = nullptr;
};
@ -233,6 +273,7 @@ KYTY_SUBSYSTEM_INIT(Pthread)
g_pthread_context->SetPthreadStaticObjects(new PthreadStaticObjects);
g_pthread_context->SetPthreadPool(new PthreadPool);
g_pthread_context->SetPthreadKeys(new PthreadKeys);
PthreadMutexattr default_mutexattr = nullptr;
PthreadRwlockattr default_rwlockattr = nullptr;
@ -461,6 +502,131 @@ void PthreadPool::FreeDetachedThreads()
}
}
bool PthreadKeys::Create(int* key, pthread_key_destructor_func_t destructor)
{
EXIT_IF(key == nullptr);
Core::LockGuard lock(m_mutex);
for (int index = 0; index < KEYS_MAX; index++)
{
if (!m_keys[index].used)
{
*key = index;
m_keys[index].used = true;
m_keys[index].destructor = destructor;
m_keys[index].specific_values.Clear();
return true;
}
}
return false;
}
bool PthreadKeys::Delete(int key)
{
Core::LockGuard lock(m_mutex);
if (key < 0 || key >= KEYS_MAX || !m_keys[key].used)
{
return false;
}
m_keys[key].used = false;
m_keys[key].destructor = nullptr;
m_keys[key].specific_values.Clear();
return true;
}
void PthreadKeys::Destruct(int thread_id)
{
Core::LockGuard lock(m_mutex);
struct CallInfo
{
pthread_key_destructor_func_t destructor;
void* data;
};
for (int iter = 0; iter < DESTRUCTOR_ITERATIONS; iter++)
{
Vector<CallInfo> delete_list;
for (auto& key: m_keys)
{
if (key.used && key.destructor != nullptr)
{
for (auto& v: key.specific_values)
{
if (v.thread_id == thread_id && v.data != nullptr)
{
delete_list.Add(CallInfo({key.destructor, v.data}));
}
}
}
}
if (delete_list.IsEmpty())
{
return;
}
for (auto& d: delete_list)
{
d.destructor(d.data);
}
}
}
bool PthreadKeys::Set(int key, int thread_id, void* data)
{
Core::LockGuard lock(m_mutex);
if (key < 0 || key >= KEYS_MAX || !m_keys[key].used)
{
return false;
}
for (auto& v: m_keys[key].specific_values)
{
if (v.thread_id == thread_id)
{
v.data = data;
return true;
}
}
m_keys[key].specific_values.Add(Map({thread_id, data}));
return true;
}
bool PthreadKeys::Get(int key, int thread_id, void** data)
{
EXIT_IF(data == nullptr);
Core::LockGuard lock(m_mutex);
if (key < 0 || key >= KEYS_MAX || !m_keys[key].used)
{
return false;
}
for (auto& v: m_keys[key].specific_values)
{
if (v.thread_id == thread_id)
{
*data = v.data;
return true;
}
}
*data = nullptr;
return true;
}
int KYTY_SYSV_ABI PthreadMutexattrInit(PthreadMutexattr* attr)
{
// PRINT_NAME();
@ -548,7 +714,10 @@ int KYTY_SYSV_ABI PthreadMutexattrSetprotocol([[maybe_unused]] PthreadMutexattr*
int KYTY_SYSV_ABI PthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr* attr, const char* name)
{
PRINT_NAME();
if (name != nullptr)
{
PRINT_NAME();
}
// EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread());
if (mutex == nullptr)
@ -569,7 +738,10 @@ int KYTY_SYSV_ABI PthreadMutexInit(PthreadMutex* mutex, const PthreadMutexattr*
int result = pthread_mutex_init(&(*mutex)->p, &(*attr)->p);
printf("\tmutex init: %s, %d\n", (*mutex)->name.C_Str(), result);
if (name != nullptr)
{
printf("\tmutex init: %s, %d\n", (*mutex)->name.C_Str(), result);
}
switch (result)
{
@ -1867,6 +2039,8 @@ int KYTY_SYSV_ABI PthreadJoin(Pthread thread, void** value)
auto* rt = Core::Singleton<Loader::RuntimeLinker>::Instance();
rt->DeleteTlss(id);
g_pthread_context->GetPthreadKeys()->Destruct(id);
switch (result)
{
case 0: return OK;
@ -1898,6 +2072,20 @@ int KYTY_SYSV_ABI PthreadCancel(Pthread thread)
}
}
int KYTY_SYSV_ABI PthreadSetaffinity(Pthread thread, KernelCpumask mask)
{
PRINT_NAME();
if (thread == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
auto result = PthreadAttrSetaffinity(&thread->attr, mask);
return result;
}
int KYTY_SYSV_ABI PthreadSetcancelstate(int state, int* old_state)
{
PRINT_NAME();
@ -1960,6 +2148,83 @@ int KYTY_SYSV_ABI PthreadSetcanceltype(int type, int* old_type)
return KERNEL_ERROR_EINVAL;
}
int KYTY_SYSV_ABI PthreadGetprio(Pthread thread, int* prio)
{
PRINT_NAME();
if (thread == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
EXIT_NOT_IMPLEMENTED(prio == nullptr);
sched_param param {};
int pol = 0;
int result = pthread_getschedparam(thread->p, &pol, &param);
if (result == 0)
{
if (param.sched_priority <= -2)
{
*prio = 767;
} else if (param.sched_priority >= +2)
{
*prio = 256;
} else
{
*prio = 700;
}
printf("\t PthreadGetprio: %d, %d\n", thread->unique_id, *prio);
return OK;
}
return KERNEL_ERROR_EINVAL;
}
int KYTY_SYSV_ABI PthreadSetprio(Pthread thread, int prio)
{
PRINT_NAME();
if (thread == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
sched_param param {};
int pol = 0;
int result = pthread_getschedparam(thread->p, &pol, &param);
if (result == 0)
{
if (prio <= 478)
{
param.sched_priority = +2;
} else if (prio >= 733)
{
param.sched_priority = -2;
} else
{
param.sched_priority = 0;
}
result = pthread_setschedparam(thread->p, pol, &param);
if (result == 0)
{
printf("\t PthreadSetprio: %d, %d\n", thread->unique_id, prio);
return OK;
}
}
return KERNEL_ERROR_EINVAL;
}
void KYTY_SYSV_ABI PthreadTestcancel()
{
PRINT_NAME();
@ -2126,84 +2391,6 @@ void KYTY_SYSV_ABI KernelSetThreadDtors(thread_dtors_func_t dtors)
// g_thread_dtors = dtors;
}
int KYTY_SYSV_ABI pthread_cond_broadcast_s(PthreadCond* cond)
{
PRINT_NAME();
// EXIT_IF(g_pthread_static_objects == nullptr);
// auto* obj = static_cast<PthreadCond*>(g_pthread_static_objects->CreateObject(cond, PthreadStaticObject::Type::Cond));
return PthreadCondBroadcast(cond);
}
int KYTY_SYSV_ABI pthread_cond_wait_s(PthreadCond* cond, PthreadMutex* mutex)
{
PRINT_NAME();
// EXIT_IF(g_pthread_static_objects == nullptr);
// auto* obj_c = static_cast<PthreadCond*>(g_pthread_static_objects->CreateObject(cond, PthreadStaticObject::Type::Cond));
// auto* obj_m = static_cast<PthreadMutex*>(g_pthread_static_objects->CreateObject(mutex, PthreadStaticObject::Type::Mutex));
return PthreadCondWait(cond, mutex);
}
int KYTY_SYSV_ABI pthread_mutex_lock_s(PthreadMutex* mutex)
{
PRINT_NAME();
// EXIT_IF(g_pthread_static_objects == nullptr);
// auto* obj = static_cast<PthreadMutex*>(g_pthread_static_objects->CreateObject(mutex, PthreadStaticObject::Type::Mutex));
return PthreadMutexLock(mutex);
}
int KYTY_SYSV_ABI pthread_mutex_unlock_s(PthreadMutex* mutex)
{
PRINT_NAME();
// EXIT_IF(g_pthread_static_objects == nullptr);
// auto* obj = static_cast<PthreadMutex*>(g_pthread_static_objects->CreateObject(mutex, PthreadStaticObject::Type::Mutex));
return PthreadMutexUnlock(mutex);
}
int KYTY_SYSV_ABI pthread_rwlock_rdlock_s(PthreadRwlock* rwlock)
{
PRINT_NAME();
// EXIT_IF(g_pthread_static_objects == nullptr);
// auto* obj = static_cast<PthreadRwlock*>(g_pthread_static_objects->CreateObject(rwlock, PthreadStaticObject::Type::Rwlock));
return PthreadRwlockRdlock(rwlock);
}
int KYTY_SYSV_ABI pthread_rwlock_unlock_s(PthreadRwlock* rwlock)
{
PRINT_NAME();
// EXIT_IF(g_pthread_static_objects == nullptr);
// auto* obj = static_cast<PthreadRwlock*>(g_pthread_static_objects->CreateObject(rwlock, PthreadStaticObject::Type::Rwlock));
return PthreadRwlockUnlock(rwlock);
}
int KYTY_SYSV_ABI pthread_rwlock_wrlock_s(PthreadRwlock* rwlock)
{
PRINT_NAME();
// EXIT_IF(g_pthread_static_objects == nullptr);
// auto* obj = static_cast<PthreadRwlock*>(g_pthread_static_objects->CreateObject(rwlock, PthreadStaticObject::Type::Rwlock));
return PthreadRwlockWrlock(rwlock);
}
int KYTY_SYSV_ABI KernelUsleep(KernelUseconds microseconds)
{
PRINT_NAME();
@ -2256,6 +2443,179 @@ int KYTY_SYSV_ABI KernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rm
return OK;
}
} // namespace Kyty::Libs::LibKernel
int KYTY_SYSV_ABI PthreadKeyCreate(PthreadKey* key, pthread_key_destructor_func_t destructor)
{
PRINT_NAME();
if (key == nullptr)
{
return KERNEL_ERROR_EINVAL;
}
EXIT_IF(g_pthread_context == nullptr || g_pthread_context->GetPthreadKeys() == nullptr);
if (!g_pthread_context->GetPthreadKeys()->Create(key, destructor))
{
return KERNEL_ERROR_EAGAIN;
}
printf("\t destructor = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(destructor));
printf("\t key = %d\n", *key);
return OK;
}
int KYTY_SYSV_ABI PthreadKeyDelete(PthreadKey key)
{
PRINT_NAME();
printf("\t key = %d\n", key);
EXIT_IF(g_pthread_context == nullptr || g_pthread_context->GetPthreadKeys() == nullptr);
if (!g_pthread_context->GetPthreadKeys()->Delete(key))
{
return KERNEL_ERROR_EINVAL;
}
return OK;
}
int KYTY_SYSV_ABI PthreadSetspecific(PthreadKey key, void* value)
{
PRINT_NAME();
int thread_id = Core::Thread::GetThreadIdUnique();
printf("\t key = %d\n", key);
printf("\t thread_id = %d\n", thread_id);
printf("\t value = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(value));
EXIT_IF(g_pthread_context == nullptr || g_pthread_context->GetPthreadKeys() == nullptr);
if (!g_pthread_context->GetPthreadKeys()->Set(key, thread_id, value))
{
return KERNEL_ERROR_EINVAL;
}
return OK;
}
void* KYTY_SYSV_ABI PthreadGetspecific(PthreadKey key)
{
PRINT_NAME();
int thread_id = Core::Thread::GetThreadIdUnique();
printf("\t key = %d\n", key);
printf("\t thread_id = %d\n", thread_id);
EXIT_IF(g_pthread_context == nullptr || g_pthread_context->GetPthreadKeys() == nullptr);
void* value = nullptr;
if (!g_pthread_context->GetPthreadKeys()->Get(key, thread_id, &value))
{
return nullptr;
}
printf("\t value = %016" PRIx64 "\n", reinterpret_cast<uint64_t>(value));
return value;
}
} // namespace LibKernel
namespace Posix {
LIB_NAME("Posix", "libkernel");
int KYTY_SYSV_ABI pthread_cond_broadcast(LibKernel::PthreadCond* cond)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadCondBroadcast(cond));
}
int KYTY_SYSV_ABI pthread_cond_wait(LibKernel::PthreadCond* cond, LibKernel::PthreadMutex* mutex)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadCondWait(cond, mutex));
}
int KYTY_SYSV_ABI pthread_mutex_lock(LibKernel::PthreadMutex* mutex)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexLock(mutex));
}
int KYTY_SYSV_ABI pthread_mutex_unlock(LibKernel::PthreadMutex* mutex)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexUnlock(mutex));
}
int KYTY_SYSV_ABI pthread_rwlock_rdlock(LibKernel::PthreadRwlock* rwlock)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadRwlockRdlock(rwlock));
}
int KYTY_SYSV_ABI pthread_rwlock_unlock(LibKernel::PthreadRwlock* rwlock)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadRwlockUnlock(rwlock));
}
int KYTY_SYSV_ABI pthread_rwlock_wrlock(LibKernel::PthreadRwlock* rwlock)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadRwlockWrlock(rwlock));
}
int KYTY_SYSV_ABI pthread_key_create(LibKernel::PthreadKey* key, LibKernel::pthread_key_destructor_func_t destructor)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadKeyCreate(key, destructor));
}
int KYTY_SYSV_ABI pthread_key_delete(LibKernel::PthreadKey key)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadKeyDelete(key));
}
int KYTY_SYSV_ABI pthread_setspecific(LibKernel::PthreadKey key, void* value)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadSetspecific(key, value));
}
int KYTY_SYSV_ABI pthread_mutex_destroy(LibKernel::PthreadMutex* mutex)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexDestroy(mutex));
}
int KYTY_SYSV_ABI pthread_mutex_init(LibKernel::PthreadMutex* mutex, const LibKernel::PthreadMutexattr* attr)
{
PRINT_NAME();
return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexInit(mutex, attr, nullptr));
}
} // namespace Posix
} // namespace Kyty::Libs
#endif // KYTY_EMU_ENABLED

View file

@ -0,0 +1,379 @@
#include "Emulator/Kernel/Semaphore.h"
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/String.h"
#include "Kyty/Core/Threads.h"
#include "Kyty/Core/Timer.h"
#include "Kyty/Core/Vector.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::LibKernel::Semaphore {
LIB_NAME("libkernel", "libkernel");
class KernelSemaPrivate
{
public:
enum class Result
{
Ok,
TimedOut,
Canceled,
Deleted,
InvalCount
};
KernelSemaPrivate(const String& name, bool fifo, int init_count, int max_count)
: m_name(name), m_fifo_order(fifo), m_count(init_count), m_init_count(init_count), m_max_count(max_count) {};
virtual ~KernelSemaPrivate();
KYTY_CLASS_NO_COPY(KernelSemaPrivate);
Result Cancel(int set_count, int* num_waiting_threads);
Result Signal(int signal_count);
Result Wait(int need_count, uint32_t* ptr_micros);
Result Poll(int need_count)
{
uint32_t micros = 0;
return Wait(need_count, &micros);
}
[[nodiscard]] const String& GetName() const { return m_name; }
private:
enum class Status
{
Set,
Canceled,
Deleted
};
Core::Mutex m_mutex;
Core::CondVar m_cond_var;
String m_name;
Status m_status = Status::Set;
Vector<int> m_waiting_threads;
[[maybe_unused]] bool m_fifo_order;
int m_count;
int m_init_count;
int m_max_count;
};
KernelSemaPrivate::~KernelSemaPrivate()
{
Core::LockGuard lock(m_mutex);
while (m_status != Status::Set)
{
m_mutex.Unlock();
Core::Thread::SleepMicro(10);
m_mutex.Lock();
}
m_status = Status::Deleted;
m_cond_var.SignalAll();
while (!m_waiting_threads.IsEmpty())
{
m_mutex.Unlock();
Core::Thread::SleepMicro(10);
m_mutex.Lock();
}
}
KernelSemaPrivate::Result KernelSemaPrivate::Cancel(int set_count, int* num_waiting_threads)
{
Core::LockGuard lock(m_mutex);
if (set_count > m_max_count)
{
return Result::InvalCount;
}
EXIT_NOT_IMPLEMENTED(m_status == Status::Deleted);
while (m_status != Status::Set)
{
m_mutex.Unlock();
Core::Thread::SleepMicro(10);
m_mutex.Lock();
}
if (num_waiting_threads != nullptr)
{
*num_waiting_threads = static_cast<int>(m_waiting_threads.Size());
}
m_status = Status::Canceled;
m_count = (set_count < 0 ? m_init_count : set_count);
m_cond_var.SignalAll();
while (!m_waiting_threads.IsEmpty())
{
m_mutex.Unlock();
Core::Thread::SleepMicro(10);
m_mutex.Lock();
}
m_status = Status::Set;
return Result::Ok;
}
KernelSemaPrivate::Result KernelSemaPrivate::Signal(int signal_count)
{
Core::LockGuard lock(m_mutex);
EXIT_NOT_IMPLEMENTED(m_status == Status::Deleted);
while (m_status != Status::Set)
{
m_mutex.Unlock();
Core::Thread::SleepMicro(10);
m_mutex.Lock();
}
if (m_count + signal_count > m_max_count)
{
return Result::InvalCount;
}
m_count += signal_count;
m_cond_var.SignalAll();
return Result::Ok;
}
KernelSemaPrivate::Result KernelSemaPrivate::Wait(int need_count, uint32_t* ptr_micros)
{
Core::LockGuard lock(m_mutex);
if (need_count < 1 || need_count > m_max_count)
{
return Result::InvalCount;
}
uint32_t micros = 0;
bool infinitely = true;
if (ptr_micros != nullptr)
{
micros = *ptr_micros;
infinitely = false;
}
uint32_t elapsed = 0;
Core::Timer t;
t.Start();
int id = Core::Thread::GetThreadIdUnique();
while (!(m_count - need_count >= 0))
{
if ((elapsed >= micros && !infinitely))
{
*ptr_micros = 0;
return Result::TimedOut;
}
m_waiting_threads.Add(id);
if (infinitely)
{
m_cond_var.Wait(&m_mutex);
} else
{
m_cond_var.WaitFor(&m_mutex, micros - elapsed);
}
m_waiting_threads.Remove(id);
elapsed = static_cast<uint32_t>(t.GetTimeS() * 1000000.0);
if (m_status == Status::Canceled)
{
if (ptr_micros != nullptr)
{
*ptr_micros = (elapsed >= micros ? 0 : micros - elapsed);
}
return Result::Canceled;
}
if (m_status == Status::Deleted)
{
if (ptr_micros != nullptr)
{
*ptr_micros = (elapsed >= micros ? 0 : micros - elapsed);
}
return Result::Deleted;
}
}
m_count -= need_count;
if (ptr_micros != nullptr)
{
*ptr_micros = (elapsed >= micros ? 0 : micros - elapsed);
}
return Result::Ok;
}
int KYTY_SYSV_ABI KernelCreateSema(KernelSema* sem, const char* name, uint32_t attr, int init, int max, void* opt)
{
PRINT_NAME();
EXIT_NOT_IMPLEMENTED(sem == nullptr);
if (name == nullptr || init < 0 || init > max || opt != nullptr)
{
return KERNEL_ERROR_EINVAL;
}
bool fifo = false;
switch (attr)
{
case 0x01: fifo = true; break;
case 0x02:
default: fifo = false; break;
}
*sem = new KernelSemaPrivate(String::FromUtf8(name), fifo, init, max);
printf("\t Semaphore create: %s, %d, %d\n", name, init, max);
return OK;
}
int KYTY_SYSV_ABI KernelDeleteSema(KernelSema sem)
{
PRINT_NAME();
if (sem == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
delete sem;
return OK;
}
int KYTY_SYSV_ABI KernelWaitSema(KernelSema sem, int need, KernelUseconds* time)
{
PRINT_NAME();
if (sem == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
printf("\t Semaphore wait: %s, %d, %d\n", sem->GetName().C_Str(), need, (time != nullptr ? *time : -1));
auto result = sem->Wait(need, time);
int ret = OK;
switch (result)
{
case KernelSemaPrivate::Result::Ok: ret = OK; break;
case KernelSemaPrivate::Result::InvalCount: ret = KERNEL_ERROR_EINVAL; break;
case KernelSemaPrivate::Result::TimedOut: ret = KERNEL_ERROR_ETIMEDOUT; break;
case KernelSemaPrivate::Result::Canceled: ret = KERNEL_ERROR_ECANCELED; break;
case KernelSemaPrivate::Result::Deleted: ret = KERNEL_ERROR_EACCES; break;
}
return ret;
}
int KYTY_SYSV_ABI KernelPollSema(KernelSema sem, int need)
{
PRINT_NAME();
if (sem == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
printf("\t Semaphore poll: %s, %d\n", sem->GetName().C_Str(), need);
auto result = sem->Poll(need);
int ret = OK;
switch (result)
{
case KernelSemaPrivate::Result::Ok: ret = OK; break;
case KernelSemaPrivate::Result::InvalCount: ret = KERNEL_ERROR_EINVAL; break;
case KernelSemaPrivate::Result::TimedOut:
case KernelSemaPrivate::Result::Canceled:
case KernelSemaPrivate::Result::Deleted: ret = KERNEL_ERROR_EBUSY; break;
}
return ret;
}
int KYTY_SYSV_ABI KernelSignalSema(KernelSema sem, int count)
{
PRINT_NAME();
if (sem == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
printf("\t Semaphore signal: %s, %d\n", sem->GetName().C_Str(), count);
auto result = sem->Signal(count);
int ret = OK;
switch (result)
{
case KernelSemaPrivate::Result::Ok: ret = OK; break;
case KernelSemaPrivate::Result::InvalCount:
case KernelSemaPrivate::Result::TimedOut:
case KernelSemaPrivate::Result::Canceled:
case KernelSemaPrivate::Result::Deleted: ret = KERNEL_ERROR_EINVAL; break;
}
return ret;
}
int KYTY_SYSV_ABI KernelCancelSema(KernelSema sem, int count, int* threads)
{
PRINT_NAME();
if (sem == nullptr)
{
return KERNEL_ERROR_ESRCH;
}
auto result = sem->Cancel(count, threads);
int ret = OK;
switch (result)
{
case KernelSemaPrivate::Result::Ok: ret = OK; break;
case KernelSemaPrivate::Result::InvalCount:
case KernelSemaPrivate::Result::TimedOut:
case KernelSemaPrivate::Result::Canceled:
case KernelSemaPrivate::Result::Deleted: ret = KERNEL_ERROR_EINVAL; break;
}
return ret;
}
} // namespace Kyty::Libs::LibKernel::Semaphore
#endif

View file

@ -104,6 +104,20 @@ static void Init(const Scripts::ScriptVar& cfg)
slist->InitAll(true);
}
KYTY_SCRIPT_FUNC(kyty_load_cfg_func)
{
if (Scripts::ArgGetVarCount() != 1)
{
EXIT("invalid args\n");
}
Scripts::ScriptVar cfg = Scripts::ArgGetVar(0);
Config::Load(cfg);
return 0;
}
KYTY_SCRIPT_FUNC(kyty_init_func)
{
if (Scripts::ArgGetVarCount() != 1)
@ -326,6 +340,7 @@ void kyty_help() {}
void kyty_reg()
{
Scripts::RegisterFunc("kyty_init", LuaFunc::kyty_init_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_load_cfg", LuaFunc::kyty_load_cfg_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_load_elf", LuaFunc::kyty_load_elf_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_load_symbols", LuaFunc::kyty_load_symbols_func, LuaFunc::kyty_help);
Scripts::RegisterFunc("kyty_dbg_dump", LuaFunc::kyty_dbg_dump_func, LuaFunc::kyty_help);

View file

@ -0,0 +1,16 @@
#include "Emulator/Libs/Errno.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs::Posix {
static thread_local int g_errno = 0;
KYTY_SYSV_ABI int* GetErrorAddr()
{
return &g_errno;
}
} // namespace Kyty::Libs::Posix
#endif

View file

@ -13,6 +13,13 @@ LIB_VERSION("DiscMap", 1, "DiscMap", 1, 1);
namespace DiscMap {
/*
DISC_MAP_ERROR_INVALID_ARGUMENT = 0x81100001;
DISC_MAP_ERROR_LOCATION_NOT_MAPPED = 0x81100002;
DISC_MAP_ERROR_FILE_NOT_FOUND = 0x81100003;
DISC_MAP_ERROR_NO_BITMAP_INFO = 0x81100004;
*/
static KYTY_SYSV_ABI int DiscMapIsRequestOnHDD(const char* file, uint64_t a2, uint64_t a3, const int* a4)
{
PRINT_NAME();
@ -25,7 +32,21 @@ static KYTY_SYSV_ABI int DiscMapIsRequestOnHDD(const char* file, uint64_t a2, ui
return 0;
}
static KYTY_SYSV_ABI int Unknown(const char* file, uint64_t a2, uint64_t a3, const uint64_t* a4, const uint64_t* a5, const uint64_t* a6)
static KYTY_SYSV_ABI int Unknown1(const char* file, uint64_t a2, uint64_t a3, const uint64_t* a4, const uint64_t* a5, const uint64_t* a6)
{
PRINT_NAME();
printf("\tfile = %s\n", file);
printf("\ta2 = %016" PRIx64 "\n", a2);
printf("\ta3 = %016" PRIx64 "\n", a3);
printf("\t*a4 = %016" PRIx64 "\n", *a4);
printf("\t*a5 = %016" PRIx64 "\n", *a5);
printf("\t*a6 = %016" PRIx64 "\n", *a6);
return 0;
}
static KYTY_SYSV_ABI int Unknown2(const char* file, uint64_t a2, uint64_t a3, const uint64_t* a4, const uint64_t* a5, const uint64_t* a6)
{
PRINT_NAME();
@ -44,7 +65,8 @@ static KYTY_SYSV_ABI int Unknown(const char* file, uint64_t a2, uint64_t a3, con
LIB_DEFINE(InitDiscMap_1)
{
LIB_FUNC("lbQKqsERhtE", DiscMap::DiscMapIsRequestOnHDD);
LIB_FUNC("fJgP+wqifno", DiscMap::Unknown);
LIB_FUNC("fJgP+wqifno", DiscMap::Unknown1);
LIB_FUNC("ioKMruft1ek", DiscMap::Unknown2);
}
} // namespace Kyty::Libs

View file

@ -14,7 +14,10 @@ LIB_DEFINE(InitGraphicsDriver_1)
PRINT_NAME_ENABLE(true);
LIB_FUNC("gAhCn6UiU4Y", Graphics::GraphicsSetVsShader);
LIB_FUNC("V31V01UiScY", Graphics::GraphicsUpdateVsShader);
LIB_FUNC("bQVd5YzCal0", Graphics::GraphicsSetPsShader);
LIB_FUNC("5uFKckiJYRM", Graphics::GraphicsSetPsShader350);
LIB_FUNC("4MgRw-bVNQU", Graphics::GraphicsUpdatePsShader);
LIB_FUNC("Kx-h-nWQJ8A", Graphics::GraphicsSetCsShaderWithModifier);
LIB_FUNC("HlTPoZ-oY7Y", Graphics::GraphicsDrawIndex);
LIB_FUNC("GGsn7jMTxw4", Graphics::GraphicsDrawIndexAuto);
@ -25,6 +28,9 @@ LIB_DEFINE(InitGraphicsDriver_1)
LIB_FUNC("iBt3Oe00Kvc", Graphics::GraphicsFlushMemory);
LIB_FUNC("b0xyllnVY-I", Graphics::GraphicsAddEqEvent);
LIB_FUNC("PVT+fuoS9gU", Graphics::GraphicsDeleteEqEvent);
LIB_FUNC("Idffwf3yh8s", Graphics::GraphicsDrawInitDefaultHardwareState);
LIB_FUNC("QhnyReteJ1M", Graphics::GraphicsDrawInitDefaultHardwareState175);
LIB_FUNC("0H2vBYbTLHI", Graphics::GraphicsDrawInitDefaultHardwareState200);
LIB_FUNC("yb2cRhagD1I", Graphics::GraphicsDrawInitDefaultHardwareState350);
LIB_FUNC("nF6bFRUBRAU", Graphics::GraphicsDispatchInitDefaultHardwareState);
LIB_FUNC("1qXLHIpROPE", Graphics::GraphicsInsertWaitFlipDone);
@ -39,6 +45,7 @@ LIB_DEFINE(InitGraphicsDriver_1)
LIB_FUNC("ZFqKFl23aMc", Graphics::GraphicsRegisterOwner);
LIB_FUNC("nvEwfYAImTs", Graphics::GraphicsRegisterResource);
LIB_FUNC("Fwvh++m9IQI", Graphics::GraphicsGetGpuCoreClockFrequency);
LIB_FUNC("jg33rEKLfVs", Graphics::GraphicsIsUserPaEnabled);
}
} // namespace Kyty::Libs

View file

@ -11,6 +11,7 @@
#include "Emulator/Kernel/FileSystem.h"
#include "Emulator/Kernel/Memory.h"
#include "Emulator/Kernel/Pthread.h"
#include "Emulator/Kernel/Semaphore.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/RuntimeLinker.h"
@ -102,23 +103,16 @@ static const char* g_progname = g_progname_buf;
static get_thread_atexit_count_func_t g_get_thread_atexit_count_func = nullptr;
static thread_atexit_report_func_t g_thread_atexit_report_func = nullptr;
static thread_local int g_errno = 0;
void SetProgName(const String& name)
{
strncpy(g_progname_buf, name.C_Str(), PROGNAME_MAX_SIZE);
}
// struct KernelContext
//{
// Vector<Loader::Program*> programs;
//};
static KYTY_SYSV_ABI int* get_error_addr()
{
PRINT_NAME();
return &g_errno;
return Posix::GetErrorAddr();
}
static KYTY_SYSV_ABI void stack_chk_fail()
@ -415,17 +409,22 @@ int KYTY_SYSV_ABI clock_gettime(int clock_id, LibKernel::KernelTimespec* time)
{
PRINT_NAME();
if (LibKernel::KernelClockGettime(clock_id, time) < 0)
{
return -1;
}
return 0;
return POSIX_CALL(LibKernel::KernelClockGettime(clock_id, time));
}
LIB_DEFINE(InitLibKernel_1_Posix)
{
LIB_FUNC("lLMT9vJAck0", clock_gettime);
LIB_FUNC("7H0iTOciTLo", Posix::pthread_mutex_lock);
LIB_FUNC("2Z+PpY6CaJg", Posix::pthread_mutex_unlock);
LIB_FUNC("ttHNfU+qDBU", Posix::pthread_mutex_init);
LIB_FUNC("ltCfaGr2JGE", Posix::pthread_mutex_destroy);
LIB_FUNC("mkx2fVhNMsg", Posix::pthread_cond_broadcast);
LIB_FUNC("Op8TBGY5KHg", Posix::pthread_cond_wait);
LIB_FUNC("mqULNdimTn0", Posix::pthread_key_create);
LIB_FUNC("6BpEZuDT7YI", Posix::pthread_key_delete);
LIB_FUNC("WrOLvHU0yQM", Posix::pthread_setspecific);
}
} // namespace Posix
@ -434,6 +433,7 @@ namespace FileSystem = LibKernel::FileSystem;
namespace Memory = LibKernel::Memory;
namespace EventQueue = LibKernel::EventQueue;
namespace EventFlag = LibKernel::EventFlag;
namespace Semaphore = LibKernel::Semaphore;
LIB_DEFINE(InitLibKernel_1_FS)
{
@ -459,6 +459,7 @@ LIB_DEFINE(InitLibKernel_1_Mem)
LIB_FUNC("L-Q3LEjIbgA", Memory::KernelMapDirectMemory);
LIB_FUNC("MBuItvba6z8", Memory::KernelReleaseDirectMemory);
LIB_FUNC("WFcfL2lzido", Memory::KernelQueryMemoryProtection);
LIB_FUNC("BHouLQzh0X0", Memory::KernelDirectMemoryQuery);
}
LIB_DEFINE(InitLibKernel_1_Equeue)
@ -475,6 +476,14 @@ LIB_DEFINE(InitLibKernel_1_EventFlag)
LIB_FUNC("JTvBflhYazQ", EventFlag::KernelWaitEventFlag);
}
LIB_DEFINE(InitLibKernel_1_Semaphore)
{
LIB_FUNC("188x57JYp0g", Semaphore::KernelCreateSema);
LIB_FUNC("R1Jvn8bSCW8", Semaphore::KernelDeleteSema);
LIB_FUNC("Zxa0VhQVTsk", Semaphore::KernelWaitSema);
LIB_FUNC("4czppHBiriw", Semaphore::KernelSignalSema);
}
LIB_DEFINE(InitLibKernel_1_Pthread)
{
LIB_FUNC("9UK1vLZQft4", LibKernel::PthreadMutexLock);
@ -493,6 +502,9 @@ LIB_DEFINE(InitLibKernel_1_Pthread)
LIB_FUNC("onNY9Byn-W8", LibKernel::PthreadJoin);
LIB_FUNC("4qGrR6eoP9Y", LibKernel::PthreadDetach);
LIB_FUNC("How7B8Oet6k", LibKernel::PthreadGetname);
LIB_FUNC("bt3CTBKmGyI", LibKernel::PthreadSetaffinity);
LIB_FUNC("1tKyG7RlMJo", LibKernel::PthreadGetprio);
LIB_FUNC("W0Hpm2X0uPE", LibKernel::PthreadSetprio);
LIB_FUNC("62KCwEMmzcM", LibKernel::PthreadAttrDestroy);
LIB_FUNC("x1X76arYMxU", LibKernel::PthreadAttrGet);
@ -504,6 +516,7 @@ LIB_DEFINE(InitLibKernel_1_Pthread)
LIB_FUNC("eXbUSpEaTsA", LibKernel::PthreadAttrSetinheritsched);
LIB_FUNC("DzES9hQF4f4", LibKernel::PthreadAttrSetschedparam);
LIB_FUNC("4+h9EzwKF4I", LibKernel::PthreadAttrSetschedpolicy);
LIB_FUNC("3qxgM4ezETA", LibKernel::PthreadAttrSetaffinity);
LIB_FUNC("6ULAa0fq4jA", LibKernel::PthreadRwlockInit);
LIB_FUNC("BB+kb08Tl9A", LibKernel::PthreadRwlockDestroy);
@ -522,10 +535,10 @@ LIB_DEFINE(InitLibKernel_1_Pthread)
LIB_FUNC("1j3S3n-tTW4", LibKernel::KernelGetTscFrequency);
LIB_FUNC("4J2sUJmuHZQ", LibKernel::KernelGetProcessTime);
LIB_FUNC("7H0iTOciTLo", LibKernel::pthread_mutex_lock_s);
LIB_FUNC("2Z+PpY6CaJg", LibKernel::pthread_mutex_unlock_s);
LIB_FUNC("mkx2fVhNMsg", LibKernel::pthread_cond_broadcast_s);
LIB_FUNC("Op8TBGY5KHg", LibKernel::pthread_cond_wait_s);
LIB_FUNC("7H0iTOciTLo", Posix::pthread_mutex_lock);
LIB_FUNC("2Z+PpY6CaJg", Posix::pthread_mutex_unlock);
LIB_FUNC("mkx2fVhNMsg", Posix::pthread_cond_broadcast);
LIB_FUNC("Op8TBGY5KHg", Posix::pthread_cond_wait);
}
LIB_DEFINE(InitLibKernel_1)
@ -534,6 +547,7 @@ LIB_DEFINE(InitLibKernel_1)
InitLibKernel_1_Mem(s);
InitLibKernel_1_Equeue(s);
InitLibKernel_1_EventFlag(s);
InitLibKernel_1_Semaphore(s);
InitLibKernel_1_Pthread(s);
Posix::InitLibKernel_1_Posix(s);

View file

@ -0,0 +1,129 @@
#include "Kyty/Core/DbgAssert.h"
#include "Kyty/Core/String.h"
#include "Emulator/Common.h"
#include "Emulator/Libs/Errno.h"
#include "Emulator/Libs/Libs.h"
#include "Emulator/SymbolDatabase.h"
#ifdef KYTY_EMU_ENABLED
namespace Kyty::Libs {
LIB_VERSION("SystemService", 1, "SystemService", 1, 1);
namespace SystemService {
[[maybe_unused]] constexpr int PARAM_ID_LANG = 1;
[[maybe_unused]] constexpr int PARAM_ID_DATE_FORMAT = 2;
[[maybe_unused]] constexpr int PARAM_ID_TIME_FORMAT = 3;
[[maybe_unused]] constexpr int PARAM_ID_TIME_ZONE = 4;
[[maybe_unused]] constexpr int PARAM_ID_SUMMERTIME = 5;
[[maybe_unused]] constexpr int PARAM_ID_SYSTEM_NAME = 6;
[[maybe_unused]] constexpr int PARAM_ID_GAME_PARENTAL_LEVEL = 7;
[[maybe_unused]] constexpr int PARAM_ID_ENTER_BUTTON_ASSIGN = 1000;
[[maybe_unused]] constexpr int PARAM_LANG_JAPANESE = 0;
[[maybe_unused]] constexpr int PARAM_LANG_ENGLISH_US = 1;
[[maybe_unused]] constexpr int PARAM_LANG_FRENCH = 2;
[[maybe_unused]] constexpr int PARAM_LANG_SPANISH = 3;
[[maybe_unused]] constexpr int PARAM_LANG_GERMAN = 4;
[[maybe_unused]] constexpr int PARAM_LANG_ITALIAN = 5;
[[maybe_unused]] constexpr int PARAM_LANG_DUTCH = 6;
[[maybe_unused]] constexpr int PARAM_LANG_PORTUGUESE_PT = 7;
[[maybe_unused]] constexpr int PARAM_LANG_RUSSIAN = 8;
[[maybe_unused]] constexpr int PARAM_LANG_KOREAN = 9;
[[maybe_unused]] constexpr int PARAM_LANG_CHINESE_T = 10;
[[maybe_unused]] constexpr int PARAM_LANG_CHINESE_S = 11;
[[maybe_unused]] constexpr int PARAM_LANG_FINNISH = 12;
[[maybe_unused]] constexpr int PARAM_LANG_SWEDISH = 13;
[[maybe_unused]] constexpr int PARAM_LANG_DANISH = 14;
[[maybe_unused]] constexpr int PARAM_LANG_NORWEGIAN = 15;
[[maybe_unused]] constexpr int PARAM_LANG_POLISH = 16;
[[maybe_unused]] constexpr int PARAM_LANG_PORTUGUESE_BR = 17;
[[maybe_unused]] constexpr int PARAM_LANG_ENGLISH_GB = 18;
[[maybe_unused]] constexpr int PARAM_LANG_TURKISH = 19;
[[maybe_unused]] constexpr int PARAM_LANG_SPANISH_LA = 20;
[[maybe_unused]] constexpr int PARAM_LANG_ARABIC = 21;
[[maybe_unused]] constexpr int PARAM_LANG_FRENCH_CA = 22;
[[maybe_unused]] constexpr int PARAM_LANG_CZECH = 23;
[[maybe_unused]] constexpr int PARAM_LANG_HUNGARIAN = 24;
[[maybe_unused]] constexpr int PARAM_LANG_GREEK = 25;
[[maybe_unused]] constexpr int PARAM_LANG_ROMANIAN = 26;
[[maybe_unused]] constexpr int PARAM_LANG_THAI = 27;
[[maybe_unused]] constexpr int PARAM_LANG_VIETNAMESE = 28;
[[maybe_unused]] constexpr int PARAM_LANG_INDONESIAN = 29;
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_YYYYMMDD = 0;
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_DDMMYYYY = 1;
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_MMDDYYYY = 2;
[[maybe_unused]] constexpr int PARAM_TIME_FORMAT_12HOUR = 0;
[[maybe_unused]] constexpr int PARAM_TIME_FORMAT_24HOUR = 1;
[[maybe_unused]] constexpr int MAX_SYSTEM_NAME_LENGTH = 65;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_OFF = 0;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL01 = 1;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL02 = 2;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL03 = 3;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL04 = 4;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL05 = 5;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL06 = 6;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL07 = 7;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL08 = 8;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL09 = 9;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL10 = 10;
[[maybe_unused]] constexpr int PARAM_GAME_PARENTAL_LEVEL11 = 11;
[[maybe_unused]] constexpr int PARAM_ENTER_BUTTON_ASSIGN_CIRCLE = 0;
[[maybe_unused]] constexpr int PARAM_ENTER_BUTTON_ASSIGN_CROSS = 1;
static int KYTY_SYSV_ABI SystemServiceHideSplashScreen()
{
PRINT_NAME();
return OK;
}
static int KYTY_SYSV_ABI SystemServiceParamGetInt(int param_id, int* value)
{
PRINT_NAME();
if (value == nullptr)
{
return SYSTEM_SERVICE_ERROR_PARAMETER;
}
int v = 0;
switch (param_id)
{
case PARAM_ID_LANG: v = PARAM_LANG_RUSSIAN; break;
case PARAM_ID_DATE_FORMAT: v = PARAM_DATE_FORMAT_DDMMYYYY; break;
case PARAM_ID_TIME_FORMAT: v = PARAM_TIME_FORMAT_24HOUR; break;
case PARAM_ID_TIME_ZONE: v = +180; break;
case PARAM_ID_SUMMERTIME: v = 0; break;
case PARAM_ID_GAME_PARENTAL_LEVEL: v = PARAM_GAME_PARENTAL_OFF; break;
case PARAM_ID_ENTER_BUTTON_ASSIGN: v = PARAM_ENTER_BUTTON_ASSIGN_CROSS; break;
default: EXIT("unknown param_id: %d\n", param_id);
}
printf(" %d = %d\n", param_id, v);
*value = v;
return OK;
}
} // namespace SystemService
LIB_DEFINE(InitSystemService_1)
{
LIB_FUNC("Vo5V8KAwCmk", SystemService::SystemServiceHideSplashScreen);
LIB_FUNC("fZo48un7LK4", SystemService::SystemServiceParamGetInt);
}
} // namespace Kyty::Libs
#endif // KYTY_EMU_ENABLED

View file

@ -15,6 +15,7 @@ LIB_DEFINE(InitSysmodule_1);
LIB_DEFINE(InitDiscMap_1);
LIB_DEFINE(InitDebug_1);
LIB_DEFINE(InitGraphicsDriver_1);
LIB_DEFINE(InitSystemService_1);
LIB_DEFINE(InitUserService_1);
LIB_DEFINE(InitPad_1);
@ -29,6 +30,7 @@ bool Init(const String& id, Loader::SymbolDatabase* s)
LIB_CHECK(U"libDebug_1", InitDebug_1);
LIB_CHECK(U"libGraphicsDriver_1", InitGraphicsDriver_1);
LIB_CHECK(U"libUserService_1", InitUserService_1);
LIB_CHECK(U"libSystemService_1", InitSystemService_1);
LIB_CHECK(U"libPad_1", InitPad_1);
return false;

View file

@ -20,7 +20,7 @@
#define KYTY_LIBS \
{ \
"libc_internal_1", "libkernel_1", "libVideoOut_1", "libSysmodule_1", "libDiscMap_1", "libDebug_1", "libGraphicsDriver_1", \
"libUserService_1", "libPad_1" \
"libUserService_1", "libSystemService_1", "libPad_1" \
}
template <class T>

View file

@ -1,5 +1,6 @@
#include "Kyty/Core/MemoryAlloc.h"
#include "Kyty/Core/ArrayWrapper.h"
#include "Kyty/Core/Common.h"
#include "Kyty/Core/DateTime.h" // IWYU pragma: keep
#include "Kyty/Core/Debug.h" // IWYU pragma: keep