diff --git a/appveyor.yml b/appveyor.yml index 8c387a8..1883953 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.0.7.build-{build} +version: 0.0.8.build-{build} image: Visual Studio 2019 environment: matrix: diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index a00b6e7..1b46d63 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -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) diff --git a/source/emulator/include/Emulator/Graphics/Graphics.h b/source/emulator/include/Emulator/Graphics/Graphics.h index 2189aed..9f92c6c 100644 --- a/source/emulator/include/Emulator/Graphics/Graphics.h +++ b/source/emulator/include/Emulator/Graphics/Graphics.h @@ -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, diff --git a/source/emulator/include/Emulator/Graphics/HardwareContext.h b/source/emulator/include/Emulator/Graphics/HardwareContext.h index 52c8e24..65b8884 100644 --- a/source/emulator/include/Emulator/Graphics/HardwareContext.h +++ b/source/emulator/include/Emulator/Graphics/HardwareContext.h @@ -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 diff --git a/source/emulator/include/Emulator/Graphics/Pm4.h b/source/emulator/include/Emulator/Graphics/Pm4.h index 5ed19e4..8f03a43 100644 --- a/source/emulator/include/Emulator/Graphics/Pm4.h +++ b/source/emulator/include/Emulator/Graphics/Pm4.h @@ -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; diff --git a/source/emulator/include/Emulator/Graphics/Shader.h b/source/emulator/include/Emulator/Graphics/Shader.h index 1867f13..64ef63a 100644 --- a/source/emulator/include/Emulator/Graphics/Shader.h +++ b/source/emulator/include/Emulator/Graphics/Shader.h @@ -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; diff --git a/source/emulator/include/Emulator/Kernel/Memory.h b/source/emulator/include/Emulator/Kernel/Memory.h index 990ca58..31b807e 100644 --- a/source/emulator/include/Emulator/Kernel/Memory.h +++ b/source/emulator/include/Emulator/Kernel/Memory.h @@ -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 diff --git a/source/emulator/include/Emulator/Kernel/Pthread.h b/source/emulator/include/Emulator/Kernel/Pthread.h index d455ad4..550c9f6 100644 --- a/source/emulator/include/Emulator/Kernel/Pthread.h +++ b/source/emulator/include/Emulator/Kernel/Pthread.h @@ -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 diff --git a/source/emulator/include/Emulator/Kernel/Semaphore.h b/source/emulator/include/Emulator/Kernel/Semaphore.h new file mode 100644 index 0000000..916a0ba --- /dev/null +++ b/source/emulator/include/Emulator/Kernel/Semaphore.h @@ -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_ */ diff --git a/source/emulator/include/Emulator/Libs/Errno.h b/source/emulator/include/Emulator/Libs/Errno.h index 3607aae..0bf3953 100644 --- a/source/emulator/include/Emulator/Libs/Errno.h +++ b/source/emulator/include/Emulator/Libs/Errno.h @@ -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 diff --git a/source/emulator/src/Graphics/Graphics.cpp b/source/emulator/src/Graphics/Graphics.cpp index 8f112cd..52ea2cb 100644 --- a/source/emulator/src/Graphics/Graphics.cpp +++ b/source/emulator/src/Graphics/Graphics.cpp @@ -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(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(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(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(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(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(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(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(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(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(); diff --git a/source/emulator/src/Graphics/GraphicsRender.cpp b/source/emulator/src/Graphics/GraphicsRender.cpp index 86397a9..6528c71 100644 --- a/source/emulator/src/Graphics/GraphicsRender.cpp +++ b/source/emulator/src/Graphics/GraphicsRender.cpp @@ -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::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::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); diff --git a/source/emulator/src/Graphics/GraphicsRun.cpp b/source/emulator/src/Graphics/GraphicsRun.cpp index 5ee35c0..0b56016 100644 --- a/source/emulator/src/Graphics/GraphicsRun.cpp +++ b/source/emulator/src/Graphics/GraphicsRun.cpp @@ -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(&buffer[0]); + r.green = *reinterpret_cast(&buffer[1]); + r.blue = *reinterpret_cast(&buffer[2]); + r.alpha = *reinterpret_cast(&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; diff --git a/source/emulator/src/Graphics/Pm4.cpp b/source/emulator/src/Graphics/Pm4.cpp index 771f794..36d83ec 100644 --- a/source/emulator/src/Graphics/Pm4.cpp +++ b/source/emulator/src/Graphics/Pm4.cpp @@ -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"; diff --git a/source/emulator/src/Graphics/Shader.cpp b/source/emulator/src/Graphics/Shader.cpp index 1dd8777..e339d14 100644 --- a/source/emulator/src/Graphics/Shader.cpp +++ b/source/emulator/src/Graphics/Shader.cpp @@ -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(r.LodHdwCntEn())); + ret->ids.Add(bind.textures2D.slots[i]); ret->ids.Add(bind.textures2D.start_register[i]); ret->ids.Add(static_cast(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(bind.samplers.extended[i])); } diff --git a/source/emulator/src/Kernel/Memory.cpp b/source/emulator/src/Kernel/Memory.cpp index 59f4a72..755d550 100644 --- a/source/emulator/src/Kernel/Memory.cpp +++ b/source/emulator/src/Kernel/Memory.cpp @@ -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(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 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(info); + + query_info->start = static_cast(block.start_addr); + query_info->end = static_cast(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; diff --git a/source/emulator/src/Kernel/Pthread.cpp b/source/emulator/src/Kernel/Pthread.cpp index 2297ea0..9c0f39b 100644 --- a/source/emulator/src/Kernel/Pthread.cpp +++ b/source/emulator/src/Kernel/Pthread.cpp @@ -23,10 +23,15 @@ #include #include -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 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 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 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::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, ¶m); + + 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, ¶m); + + 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, ¶m); + + 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(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(g_pthread_static_objects->CreateObject(cond, PthreadStaticObject::Type::Cond)); - // auto* obj_m = static_cast(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(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(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(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(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(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(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(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(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 diff --git a/source/emulator/src/Kernel/Semaphore.cpp b/source/emulator/src/Kernel/Semaphore.cpp new file mode 100644 index 0000000..9b81392 --- /dev/null +++ b/source/emulator/src/Kernel/Semaphore.cpp @@ -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, µs); + } + + [[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 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(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(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 diff --git a/source/emulator/src/Kyty.cpp b/source/emulator/src/Kyty.cpp index 6c0fa26..df591c4 100644 --- a/source/emulator/src/Kyty.cpp +++ b/source/emulator/src/Kyty.cpp @@ -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); diff --git a/source/emulator/src/Libs/Errno.cpp b/source/emulator/src/Libs/Errno.cpp new file mode 100644 index 0000000..843960f --- /dev/null +++ b/source/emulator/src/Libs/Errno.cpp @@ -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 diff --git a/source/emulator/src/Libs/LibDiscMap.cpp b/source/emulator/src/Libs/LibDiscMap.cpp index ac53292..de018a4 100644 --- a/source/emulator/src/Libs/LibDiscMap.cpp +++ b/source/emulator/src/Libs/LibDiscMap.cpp @@ -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 diff --git a/source/emulator/src/Libs/LibGraphicsDriver.cpp b/source/emulator/src/Libs/LibGraphicsDriver.cpp index c31c25f..baf37f1 100644 --- a/source/emulator/src/Libs/LibGraphicsDriver.cpp +++ b/source/emulator/src/Libs/LibGraphicsDriver.cpp @@ -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 diff --git a/source/emulator/src/Libs/LibKernel.cpp b/source/emulator/src/Libs/LibKernel.cpp index 0dca969..a9b058d 100644 --- a/source/emulator/src/Libs/LibKernel.cpp +++ b/source/emulator/src/Libs/LibKernel.cpp @@ -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 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); diff --git a/source/emulator/src/Libs/LibSystemService.cpp b/source/emulator/src/Libs/LibSystemService.cpp new file mode 100644 index 0000000..dce94c8 --- /dev/null +++ b/source/emulator/src/Libs/LibSystemService.cpp @@ -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 diff --git a/source/emulator/src/Libs/Libs.cpp b/source/emulator/src/Libs/Libs.cpp index eb21bef..cbcce9e 100644 --- a/source/emulator/src/Libs/Libs.cpp +++ b/source/emulator/src/Libs/Libs.cpp @@ -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; diff --git a/source/launcher/include/Configuration.h b/source/launcher/include/Configuration.h index 23235ad..78a5ae4 100644 --- a/source/launcher/include/Configuration.h +++ b/source/launcher/include/Configuration.h @@ -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 diff --git a/source/lib/Core/src/MemoryAlloc.cpp b/source/lib/Core/src/MemoryAlloc.cpp index db086ce..3a6d1bd 100644 --- a/source/lib/Core/src/MemoryAlloc.cpp +++ b/source/lib/Core/src/MemoryAlloc.cpp @@ -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