diff --git a/appveyor.yml b/appveyor.yml index d2162e6..9243ce4 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.0.12.build-{build} +version: 0.0.13.build-{build} image: Visual Studio 2019 environment: matrix: diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index b8308c1..4f65c00 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.12) +project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.13) include(src_script.cmake) diff --git a/source/emulator/include/Emulator/Audio.h b/source/emulator/include/Emulator/Audio.h new file mode 100644 index 0000000..a10dbc7 --- /dev/null +++ b/source/emulator/include/Emulator/Audio.h @@ -0,0 +1,25 @@ +#ifndef EMULATOR_INCLUDE_EMULATOR_AUDIO_H_ +#define EMULATOR_INCLUDE_EMULATOR_AUDIO_H_ + +#include "Kyty/Core/Common.h" +#include "Kyty/Core/Subsystems.h" + +#include "Emulator/Common.h" + +#ifdef KYTY_EMU_ENABLED + +namespace Kyty::Libs::Audio { + +KYTY_SUBSYSTEM_DEFINE(Audio); + +namespace VoiceQoS { + +int KYTY_SYSV_ABI VoiceQoSInit(void* mem_block, uint32_t mem_size, int32_t app_type); + +} // namespace VoiceQoS + +} // namespace Kyty::Libs::Audio + +#endif // KYTY_EMU_ENABLED + +#endif /* EMULATOR_INCLUDE_EMULATOR_AUDIO_H_ */ diff --git a/source/emulator/include/Emulator/Dialog.h b/source/emulator/include/Emulator/Dialog.h new file mode 100644 index 0000000..bf59386 --- /dev/null +++ b/source/emulator/include/Emulator/Dialog.h @@ -0,0 +1,20 @@ +#ifndef EMULATOR_INCLUDE_EMULATOR_DIALOG_H_ +#define EMULATOR_INCLUDE_EMULATOR_DIALOG_H_ + +#include "Emulator/Common.h" + +#ifdef KYTY_EMU_ENABLED + +namespace Kyty::Libs::Dialog { + +namespace CommonDialog { + +int KYTY_SYSV_ABI CommonDialogInitialize(); + +} // namespace CommonDialog + +} // namespace Kyty::Libs::Dialog + +#endif // KYTY_EMU_ENABLED + +#endif /* EMULATOR_INCLUDE_EMULATOR_DIALOG_H_ */ diff --git a/source/emulator/include/Emulator/Elf.h b/source/emulator/include/Emulator/Elf.h index dd2c137..712ddc6 100644 --- a/source/emulator/include/Emulator/Elf.h +++ b/source/emulator/include/Emulator/Elf.h @@ -254,6 +254,7 @@ public: virtual ~Elf64(); void Open(const String& file_name); + void Save(const String& file_name); void DbgDump(const String& folder); diff --git a/source/emulator/include/Emulator/Graphics/GraphicsRender.h b/source/emulator/include/Emulator/Graphics/GraphicsRender.h index 006923a..ee1392d 100644 --- a/source/emulator/include/Emulator/Graphics/GraphicsRender.h +++ b/source/emulator/include/Emulator/Graphics/GraphicsRender.h @@ -89,6 +89,7 @@ void GraphicsRenderDispatchDirect(CommandBuffer* buffer, HW::HardwareContext* ct uint32_t thread_group_z, uint32_t mode); void GraphicsRenderMemoryBarrier(CommandBuffer* buffer); void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size); +void GraphicsRenderDepthStencilBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size); void GraphicsRenderMemoryFree(uint64_t vaddr, uint64_t size); void DeleteFramebuffer(VideoOutVulkanImage* image); diff --git a/source/emulator/include/Emulator/Graphics/HardwareContext.h b/source/emulator/include/Emulator/Graphics/HardwareContext.h index 60b6fb5..30126dc 100644 --- a/source/emulator/include/Emulator/Graphics/HardwareContext.h +++ b/source/emulator/include/Emulator/Graphics/HardwareContext.h @@ -534,6 +534,15 @@ public: m_vs.vs_shader_modifier = shader_modifier; m_vs.vs_embedded = false; } + void UpdateVsShader(const VsStageRegisters* vs_regs, uint32_t shader_modifier) + { + m_vs.vs_regs.m_spiShaderPgmLoVs = vs_regs->m_spiShaderPgmLoVs; + m_vs.vs_regs.m_spiShaderPgmHiVs = vs_regs->m_spiShaderPgmHiVs; + m_vs.vs_regs.m_spiShaderPgmRsrc1Vs = vs_regs->m_spiShaderPgmRsrc1Vs; + m_vs.vs_regs.m_spiShaderPgmRsrc2Vs = vs_regs->m_spiShaderPgmRsrc2Vs; + m_vs.vs_shader_modifier = shader_modifier; + m_vs.vs_embedded = false; + } void SetVsEmbedded(uint32_t id, uint32_t shader_modifier) { m_vs.vs_embedded_id = id; @@ -546,6 +555,17 @@ public: m_ps.ps_regs = *ps_regs; m_ps.ps_embedded = false; } + void UpdatePsShader(const PsStageRegisters* ps_regs) + { + m_ps.ps_regs.data_addr = ps_regs->data_addr; + m_ps.ps_regs.vgprs = ps_regs->vgprs; + m_ps.ps_regs.sgprs = ps_regs->sgprs; + m_ps.ps_regs.scratch_en = ps_regs->scratch_en; + m_ps.ps_regs.user_sgpr = ps_regs->user_sgpr; + m_ps.ps_regs.wave_cnt_en = ps_regs->wave_cnt_en; + m_ps.ps_regs.shader_z_format = ps_regs->shader_z_format; + m_ps.ps_embedded = false; + } void SetPsEmbedded(uint32_t id) { m_ps.ps_embedded_id = id; diff --git a/source/emulator/include/Emulator/Graphics/Objects/RenderTexture.h b/source/emulator/include/Emulator/Graphics/Objects/RenderTexture.h index bd9ca27..ac262a4 100644 --- a/source/emulator/include/Emulator/Graphics/Objects/RenderTexture.h +++ b/source/emulator/include/Emulator/Graphics/Objects/RenderTexture.h @@ -12,7 +12,9 @@ namespace Kyty::Libs::Graphics { enum class RenderTextureFormat : uint64_t { - R8G8B8A8Unorm + Unknown, + R8G8B8A8Unorm, + B8G8R8A8Unorm }; class RenderTextureObject: public GpuObject diff --git a/source/emulator/include/Emulator/Graphics/Shader.h b/source/emulator/include/Emulator/Graphics/Shader.h index 89f380d..71a58da 100644 --- a/source/emulator/include/Emulator/Graphics/Shader.h +++ b/source/emulator/include/Emulator/Graphics/Shader.h @@ -239,6 +239,7 @@ enum FormatByte : uint64_t L, // label_%u DmaskF, // dmask:0xf Dmask7, // dmask:0x7 + Dmask1, // dmask:0x1 Gds, // gds }; @@ -286,6 +287,7 @@ enum Format : uint64_t Vdata4VaddrSvSoffsIdxen = FormatDefine({DA4, S0, S1A4, S2, Idxen}), Vdata4VaddrSvSoffsIdxenFloat4 = FormatDefine({DA4, S0, S1A4, S2, Idxen, Float4}), Vdata4Vaddr2SvSoffsOffenIdxenFloat4 = FormatDefine({DA4, S0A2, S1A4, S2, Offen, Idxen, Float4}), + Vdata1Vaddr3StSsDmask1 = FormatDefine({D, S0A3, S1A8, S2A4, Dmask1}), Vdata3Vaddr3StSsDmask7 = FormatDefine({DA3, S0A3, S1A8, S2A4, Dmask7}), Vdata4Vaddr3StSsDmaskF = FormatDefine({DA4, S0A3, S1A8, S2A4, DmaskF}), Vdata4Vaddr3StDmaskF = FormatDefine({DA4, S0A3, S1A8, DmaskF}), diff --git a/source/emulator/include/Emulator/Libs/Errno.h b/source/emulator/include/Emulator/Libs/Errno.h index 0bf3953..4c1352e 100644 --- a/source/emulator/include/Emulator/Libs/Errno.h +++ b/source/emulator/include/Emulator/Libs/Errno.h @@ -32,6 +32,19 @@ constexpr int OK = 0; return 0; \ }() +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define POSIX_NET_CALL(func) \ + [&]() \ + { \ + auto result = func; \ + if (result != OK) \ + { \ + *GetErrorAddr() = Network::NetToPosix(result); \ + return -1; \ + } \ + return 0; \ + }() + namespace Kyty::Libs { namespace Posix { @@ -324,6 +337,257 @@ constexpr int SYSTEM_SERVICE_ERROR_NOT_FLAG_IN_PARAM_SFO = -2136932342 } // namespace SystemService +namespace Network { + +inline int NetToPosix(int kernel_errno) +{ + return kernel_errno > -2143223551 && kernel_errno <= -2143223316 ? kernel_errno + 2143223551 + 1 : 204; +} + +constexpr int NET_ERROR_EPERM = -2143223551; /* 0x80410101 */ +constexpr int NET_ERROR_ENOENT = -2143223550; /* 0x80410102 */ +constexpr int NET_ERROR_ESRCH = -2143223549; /* 0x80410103 */ +constexpr int NET_ERROR_EINTR = -2143223548; /* 0x80410104 */ +constexpr int NET_ERROR_EIO = -2143223547; /* 0x80410105 */ +constexpr int NET_ERROR_ENXIO = -2143223546; /* 0x80410106 */ +constexpr int NET_ERROR_E2BIG = -2143223545; /* 0x80410107 */ +constexpr int NET_ERROR_ENOEXEC = -2143223544; /* 0x80410108 */ +constexpr int NET_ERROR_EBADF = -2143223543; /* 0x80410109 */ +constexpr int NET_ERROR_ECHILD = -2143223542; /* 0x8041010A */ +constexpr int NET_ERROR_EDEADLK = -2143223541; /* 0x8041010B */ +constexpr int NET_ERROR_ENOMEM = -2143223540; /* 0x8041010C */ +constexpr int NET_ERROR_EACCES = -2143223539; /* 0x8041010D */ +constexpr int NET_ERROR_EFAULT = -2143223538; /* 0x8041010E */ +constexpr int NET_ERROR_ENOTBLK = -2143223537; /* 0x8041010F */ +constexpr int NET_ERROR_EBUSY = -2143223536; /* 0x80410110 */ +constexpr int NET_ERROR_EEXIST = -2143223535; /* 0x80410111 */ +constexpr int NET_ERROR_EXDEV = -2143223534; /* 0x80410112 */ +constexpr int NET_ERROR_ENODEV = -2143223533; /* 0x80410113 */ +constexpr int NET_ERROR_ENOTDIR = -2143223532; /* 0x80410114 */ +constexpr int NET_ERROR_EISDIR = -2143223531; /* 0x80410115 */ +constexpr int NET_ERROR_EINVAL = -2143223530; /* 0x80410116 */ +constexpr int NET_ERROR_ENFILE = -2143223529; /* 0x80410117 */ +constexpr int NET_ERROR_EMFILE = -2143223528; /* 0x80410118 */ +constexpr int NET_ERROR_ENOTTY = -2143223527; /* 0x80410119 */ +constexpr int NET_ERROR_ETXTBSY = -2143223526; /* 0x8041011A */ +constexpr int NET_ERROR_EFBIG = -2143223525; /* 0x8041011B */ +constexpr int NET_ERROR_ENOSPC = -2143223524; /* 0x8041011C */ +constexpr int NET_ERROR_ESPIPE = -2143223523; /* 0x8041011D */ +constexpr int NET_ERROR_EROFS = -2143223522; /* 0x8041011E */ +constexpr int NET_ERROR_EMLINK = -2143223521; /* 0x8041011F */ +constexpr int NET_ERROR_EPIPE = -2143223520; /* 0x80410120 */ +constexpr int NET_ERROR_EDOM = -2143223519; /* 0x80410121 */ +constexpr int NET_ERROR_ERANGE = -2143223518; /* 0x80410122 */ +constexpr int NET_ERROR_EAGAIN = -2143223517; /* 0x80410123 */ +constexpr int NET_ERROR_EWOULDBLOCK = -2143223517; /* 0x80410123 */ +constexpr int NET_ERROR_EINPROGRESS = -2143223516; /* 0x80410124 */ +constexpr int NET_ERROR_EALREADY = -2143223515; /* 0x80410125 */ +constexpr int NET_ERROR_ENOTSOCK = -2143223514; /* 0x80410126 */ +constexpr int NET_ERROR_EDESTADDRREQ = -2143223513; /* 0x80410127 */ +constexpr int NET_ERROR_EMSGSIZE = -2143223512; /* 0x80410128 */ +constexpr int NET_ERROR_EPROTOTYPE = -2143223511; /* 0x80410129 */ +constexpr int NET_ERROR_ENOPROTOOPT = -2143223510; /* 0x8041012A */ +constexpr int NET_ERROR_EPROTONOSUPPORT = -2143223509; /* 0x8041012B */ +constexpr int NET_ERROR_ESOCKTNOSUPPORT = -2143223508; /* 0x8041012C */ +constexpr int NET_ERROR_EOPNOTSUPP = -2143223507; /* 0x8041012D */ +constexpr int NET_ERROR_ENOTSUP = -2143223507; /* 0x8041012D */ +constexpr int NET_ERROR_EPFNOSUPPORT = -2143223506; /* 0x8041012E */ +constexpr int NET_ERROR_EAFNOSUPPORT = -2143223505; /* 0x8041012F */ +constexpr int NET_ERROR_EADDRINUSE = -2143223504; /* 0x80410130 */ +constexpr int NET_ERROR_EADDRNOTAVAIL = -2143223503; /* 0x80410131 */ +constexpr int NET_ERROR_ENETDOWN = -2143223502; /* 0x80410132 */ +constexpr int NET_ERROR_ENETUNREACH = -2143223501; /* 0x80410133 */ +constexpr int NET_ERROR_ENETRESET = -2143223500; /* 0x80410134 */ +constexpr int NET_ERROR_ECONNABORTED = -2143223499; /* 0x80410135 */ +constexpr int NET_ERROR_ECONNRESET = -2143223498; /* 0x80410136 */ +constexpr int NET_ERROR_ENOBUFS = -2143223497; /* 0x80410137 */ +constexpr int NET_ERROR_EISCONN = -2143223496; /* 0x80410138 */ +constexpr int NET_ERROR_ENOTCONN = -2143223495; /* 0x80410139 */ +constexpr int NET_ERROR_ESHUTDOWN = -2143223494; /* 0x8041013A */ +constexpr int NET_ERROR_ETOOMANYREFS = -2143223493; /* 0x8041013B */ +constexpr int NET_ERROR_ETIMEDOUT = -2143223492; /* 0x8041013C */ +constexpr int NET_ERROR_ECONNREFUSED = -2143223491; /* 0x8041013D */ +constexpr int NET_ERROR_ELOOP = -2143223490; /* 0x8041013E */ +constexpr int NET_ERROR_ENAMETOOLONG = -2143223489; /* 0x8041013F */ +constexpr int NET_ERROR_EHOSTDOWN = -2143223488; /* 0x80410140 */ +constexpr int NET_ERROR_EHOSTUNREACH = -2143223487; /* 0x80410141 */ +constexpr int NET_ERROR_ENOTEMPTY = -2143223486; /* 0x80410142 */ +constexpr int NET_ERROR_EPROCLIM = -2143223485; /* 0x80410143 */ +constexpr int NET_ERROR_EUSERS = -2143223484; /* 0x80410144 */ +constexpr int NET_ERROR_EDQUOT = -2143223483; /* 0x80410145 */ +constexpr int NET_ERROR_ESTALE = -2143223482; /* 0x80410146 */ +constexpr int NET_ERROR_EREMOTE = -2143223481; /* 0x80410147 */ +constexpr int NET_ERROR_EBADRPC = -2143223480; /* 0x80410148 */ +constexpr int NET_ERROR_ERPCMISMATCH = -2143223479; /* 0x80410149 */ +constexpr int NET_ERROR_EPROGUNAVAIL = -2143223478; /* 0x8041014A */ +constexpr int NET_ERROR_EPROGMISMATCH = -2143223477; /* 0x8041014B */ +constexpr int NET_ERROR_EPROCUNAVAIL = -2143223476; /* 0x8041014C */ +constexpr int NET_ERROR_ENOLCK = -2143223475; /* 0x8041014D */ +constexpr int NET_ERROR_ENOSYS = -2143223474; /* 0x8041014E */ +constexpr int NET_ERROR_EFTYPE = -2143223473; /* 0x8041014F */ +constexpr int NET_ERROR_EAUTH = -2143223472; /* 0x80410150 */ +constexpr int NET_ERROR_ENEEDAUTH = -2143223471; /* 0x80410151 */ +constexpr int NET_ERROR_EIDRM = -2143223470; /* 0x80410152 */ +constexpr int NET_ERROR_ENOMS = -2143223469; /* 0x80410153 */ +constexpr int NET_ERROR_EOVERFLOW = -2143223468; /* 0x80410154 */ +constexpr int NET_ERROR_ECANCELED = -2143223467; /* 0x80410155 */ +constexpr int NET_ERROR_EPROTO = -2143223460; /* 0x8041015C */ +constexpr int NET_ERROR_EADHOC = -2143223392; /* 0x804101A0 */ +constexpr int NET_ERROR_ERESERVED161 = -2143223391; /* 0x804101A1 */ +constexpr int NET_ERROR_ERESERVED162 = -2143223390; /* 0x804101A2 */ +constexpr int NET_ERROR_EINACTIVEDISABLED = -2143223389; /* 0x804101A3 */ +constexpr int NET_ERROR_ENODATA = -2143223388; /* 0x804101A4 */ +constexpr int NET_ERROR_EDESC = -2143223387; /* 0x804101A5 */ +constexpr int NET_ERROR_EDESCTIMEDOUT = -2143223386; /* 0x804101A6 */ +constexpr int NET_ERROR_ENETINTR = -2143223385; /* 0x804101A7 */ +constexpr int NET_ERROR_ENOTINIT = -2143223352; /* 0x804101C8 */ +constexpr int NET_ERROR_ENOLIBMEM = -2143223351; /* 0x804101C9 */ +constexpr int NET_ERROR_ERESERVED202 = -2143223350; /* 0x804101CA */ +constexpr int NET_ERROR_ECALLBACK = -2143223349; /* 0x804101CB */ +constexpr int NET_ERROR_EINTERNAL = -2143223348; /* 0x804101CC */ +constexpr int NET_ERROR_ERETURN = -2143223347; /* 0x804101CD */ +constexpr int NET_ERROR_ENOALLOCMEM = -2143223346; /* 0x804101CE */ +constexpr int NET_ERROR_RESOLVER_EINTERNAL = -2143223332; /* 0x804101DC */ +constexpr int NET_ERROR_RESOLVER_EBUSY = -2143223331; /* 0x804101DD */ +constexpr int NET_ERROR_RESOLVER_ENOSPACE = -2143223330; /* 0x804101DE */ +constexpr int NET_ERROR_RESOLVER_EPACKET = -2143223329; /* 0x804101DF */ +constexpr int NET_ERROR_RESOLVER_ERESERVED224 = -2143223328; /* 0x804101E0 */ +constexpr int NET_ERROR_RESOLVER_ENODNS = -2143223327; /* 0x804101E1 */ +constexpr int NET_ERROR_RESOLVER_ETIMEDOUT = -2143223326; /* 0x804101E2 */ +constexpr int NET_ERROR_RESOLVER_ENOSUPPORT = -2143223325; /* 0x804101E3 */ +constexpr int NET_ERROR_RESOLVER_EFORMAT = -2143223324; /* 0x804101E4 */ +constexpr int NET_ERROR_RESOLVER_ESERVERFAILURE = -2143223323; /* 0x804101E5 */ +constexpr int NET_ERROR_RESOLVER_ENOHOST = -2143223322; /* 0x804101E6 */ +constexpr int NET_ERROR_RESOLVER_ENOTIMPLEMENTED = -2143223321; /* 0x804101E7 */ +constexpr int NET_ERROR_RESOLVER_ESERVERREFUSED = -2143223320; /* 0x804101E8 */ +constexpr int NET_ERROR_RESOLVER_ENORECORD = -2143223319; /* 0x804101E9 */ +constexpr int NET_ERROR_RESOLVER_EALIGNMENT = -2143223318; /* 0x804101EA */ +constexpr int NET_ERROR_RESOLVER_ENOTFOUND = -2143223317; /* 0x804101EB */ +constexpr int NET_ERROR_RESOLVER_ENOTINIT = -2143223316; /* 0x804101EC */ + +constexpr int SSL_ERROR_BEFORE_INIT = -2137657343; /* 0x8095F001 */ +constexpr int SSL_ERROR_ALREADY_INITED = -2137657342; /* 0x8095F002 */ +constexpr int SSL_ERROR_BROKEN = -2137657341; /* 0x8095F003 */ +constexpr int SSL_ERROR_NOT_FOUND = -2137657340; /* 0x8095F004 */ +constexpr int SSL_ERROR_INVALID_FORMAT = -2137657339; /* 0x8095F005 */ +constexpr int SSL_ERROR_INVALID_ID = -2137657338; /* 0x8095F006 */ +constexpr int SSL_ERROR_INVALID_VALUE = -2137657337; /* 0x8095F007 */ +constexpr int SSL_ERROR_OUT_OF_SIZE = -2137657336; /* 0x8095F008 */ +constexpr int SSL_ERROR_INTERNAL = -2137657335; /* 0x8095F009 */ +constexpr int SSL_ERROR_INVALID_CERT = -2137657334; /* 0x8095F00A */ +constexpr int SSL_ERROR_CN_CHECK = -2137657333; /* 0x8095F00B */ +constexpr int SSL_ERROR_UNKNOWN_CA = -2137657332; /* 0x8095F00C */ +constexpr int SSL_ERROR_NOT_AFTER_CHECK = -2137657331; /* 0x8095F00D */ +constexpr int SSL_ERROR_NOT_BEFORE_CHECK = -2137657330; /* 0x8095F00E */ +constexpr int SSL_ERROR_EAGAIN = -2137657329; /* 0x8095F00F */ +constexpr int SSL_ERROR_FATAL_ALERT = -2137657328; /* 0x8095F010 */ +constexpr int SSL_ERROR_BUSY = -2137657326; /* 0x8095F012 */ +constexpr int SSL_ERROR_WANT_POLLIN = -2137657325; /* 0x8095F013 */ +constexpr int SSL_ERROR_WANT_POLLOUT = -2137657324; /* 0x8095F014 */ +constexpr int SSL_ERROR_INSUFFICIENT_STACKSIZE = -2137657323; /* 0x8095F015 */ +constexpr int SSL_ERROR_APPLICATION_VERIFICATION_CALLBACK_CHECK = -2137657091; /* 0x8095F0FD */ +constexpr int SSL_ERROR_OUT_OF_MEMORY = -2137712683; /* 0x809517D5 */ +constexpr int SSL_ERROR_READ_TIMEOUT = -2137712880; /* 0x80951710 */ +constexpr int SSL_ERROR_SOCKET_CLOSED = -2137712883; /* 0x8095170D */ +constexpr int SSL_ERROR_BAD_LENGTH = -2137712781; /* 0x80951773 */ +constexpr int SSL_ERROR_INDEX_OOB = -2137712776; /* 0x80951778 */ +constexpr int SSL_ERROR_INVALID_ARG = -2137712774; /* 0x8095177A */ +constexpr int SSL_ERROR_EOF = -2137712772; /* 0x8095177C */ +constexpr int SSL_ERROR_BAD_EXPONENT = -2137712771; /* 0x8095177D */ +constexpr int SSL_ERROR_INCOMPLETE_SEARCH = -2137712770; /* 0x8095177E */ +constexpr int SSL_ERROR_INTERNAL_ERROR = -2137712769; /* 0x8095177F */ +constexpr int SSL_ERROR_BAD_CERT_LENGTH = -2137710382; /* 0x809520D2 */ +constexpr int SSL_ERROR_BAD_SIGN_ALGO = -2137710383; /* 0x809520D1 */ +constexpr int SSL_ERROR_MISMATCH_PUBLIC_KEYS = -2137710381; /* 0x809520D3 */ +constexpr int SSL_ERROR_KEY_BLOB_CORRUPT = -2137710380; /* 0x809520D4 */ + +constexpr int HTTP_ERROR_BEFORE_INIT = -2143088639; /*(0x80431001) */ +constexpr int HTTP_ERROR_ALREADY_INITED = -2143088608; /*(0x80431020) */ +constexpr int HTTP_ERROR_BUSY = -2143088607; /*(0x80431021) */ +constexpr int HTTP_ERROR_OUT_OF_MEMORY = -2143088606; /*(0x80431022) */ +constexpr int HTTP_ERROR_NOT_FOUND = -2143088603; /*(0x80431025) */ +constexpr int HTTP_ERROR_INVALID_VERSION = -2143088534; /*(0x8043106a) */ +constexpr int HTTP_ERROR_INVALID_ID = -2143088384; /*(0x80431100) */ +constexpr int HTTP_ERROR_OUT_OF_SIZE = -2143088380; /*(0x80431104) */ +constexpr int HTTP_ERROR_INVALID_VALUE = -2143088130; /*(0x804311fe) */ +constexpr int HTTP_ERROR_INVALID_URL = -2143080352; /*(0x80433060) */ +constexpr int HTTP_ERROR_UNKNOWN_SCHEME = -2143088543; /*(0x80431061) */ +constexpr int HTTP_ERROR_NETWORK = -2143088541; /*(0x80431063) */ +constexpr int HTTP_ERROR_BAD_RESPONSE = -2143088540; /*(0x80431064) */ +constexpr int HTTP_ERROR_BEFORE_SEND = -2143088539; /*(0x80431065) */ +constexpr int HTTP_ERROR_AFTER_SEND = -2143088538; /*(0x80431066) */ +constexpr int HTTP_ERROR_TIMEOUT = -2143088536; /*(0x80431068) */ +constexpr int HTTP_ERROR_UNKNOWN_AUTH_TYPE = -2143088535; /*(0x80431069) */ +constexpr int HTTP_ERROR_UNKNOWN_METHOD = -2143088533; /*(0x8043106b) */ +constexpr int HTTP_ERROR_READ_BY_HEAD_METHOD = -2143088529; /*(0x8043106f) */ +constexpr int HTTP_ERROR_NOT_IN_COM = -2143088528; /*(0x80431070) */ +constexpr int HTTP_ERROR_NO_CONTENT_LENGTH = -2143088527; /*(0x80431071) */ +constexpr int HTTP_ERROR_CHUNK_ENC = -2143088526; /*(0x80431072) */ +constexpr int HTTP_ERROR_TOO_LARGE_RESPONSE_HEADER = -2143088525; /*(0x80431073) */ +constexpr int HTTP_ERROR_SSL = -2143088523; /*(0x80431075) */ +constexpr int HTTP_ERROR_INSUFFICIENT_STACKSIZE = -2143088522; /*(0x80431076) */ +constexpr int HTTP_ERROR_ABORTED = -2143088512; /*(0x80431080) */ +constexpr int HTTP_ERROR_UNKNOWN = -2143088511; /*(0x80431081) */ +constexpr int HTTP_ERROR_EAGAIN = -2143088510; /*(0x80431082) */ +constexpr int HTTP_ERROR_PROXY = -2143088508; /*(0x80431084) */ +constexpr int HTTP_ERROR_BROKEN = -2143088507; /*(0x80431085) */ +constexpr int HTTP_ERROR_PARSE_HTTP_NOT_FOUND = -2143084507; /*(0x80432025) */ +constexpr int HTTP_ERROR_PARSE_HTTP_INVALID_RESPONSE = -2143084448; /*(0x80432060) */ +constexpr int HTTP_ERROR_PARSE_HTTP_INVALID_VALUE = -2143084034; /*(0x804321fe) */ +constexpr int HTTP_ERROR_RESOLVER_EPACKET = -2143068159; /*(0x80436001) */ +constexpr int HTTP_ERROR_RESOLVER_ENODNS = -2143068158; /*(0x80436002) */ +constexpr int HTTP_ERROR_RESOLVER_ETIMEDOUT = -2143068157; /*(0x80436003) */ +constexpr int HTTP_ERROR_RESOLVER_ENOSUPPORT = -2143068156; /*(0x80436004) */ +constexpr int HTTP_ERROR_RESOLVER_EFORMAT = -2143068155; /*(0x80436005) */ +constexpr int HTTP_ERROR_RESOLVER_ESERVERFAILURE = -2143068154; /*(0x80436006) */ +constexpr int HTTP_ERROR_RESOLVER_ENOHOST = -2143068153; /*(0x80436007) */ +constexpr int HTTP_ERROR_RESOLVER_ENOTIMPLEMENTED = -2143068152; /*(0x80436008) */ +constexpr int HTTP_ERROR_RESOLVER_ESERVERREFUSED = -2143068151; /*(0x80436009) */ +constexpr int HTTP_ERROR_RESOLVER_ENORECORD = -2143068150; /*(0x8043600a) */ +constexpr int HTTPS_ERROR_CERT = -2143072160; /*(0x80435060) */ +constexpr int HTTPS_ERROR_HANDSHAKE = -2143072159; /*(0x80435061) */ +constexpr int HTTPS_ERROR_IO = -2143072158; /*(0x80435062) */ +constexpr int HTTPS_ERROR_INTERNAL = -2143072157; /*(0x80435063) */ +constexpr int HTTPS_ERROR_PROXY = -2143072156; /*(0x80435064) */ + +} // namespace Network + +namespace PlayGo { + +constexpr int PLAYGO_ERROR_UNKNOWN = -2135818239; /* 0x80B20001 */ +constexpr int PLAYGO_ERROR_FATAL = -2135818238; /* 0x80B20002 */ +constexpr int PLAYGO_ERROR_NO_MEMORY = -2135818237; /* 0x80B20003 */ +constexpr int PLAYGO_ERROR_INVALID_ARGUMENT = -2135818236; /* 0x80B20004 */ +constexpr int PLAYGO_ERROR_NOT_INITIALIZED = -2135818235; /* 0x80B20005 */ +constexpr int PLAYGO_ERROR_ALREADY_INITIALIZED = -2135818234; /* 0x80B20006 */ +constexpr int PLAYGO_ERROR_ALREADY_STARTED = -2135818233; /* 0x80B20007 */ +constexpr int PLAYGO_ERROR_NOT_STARTED = -2135818232; /* 0x80B20008 */ +constexpr int PLAYGO_ERROR_BAD_HANDLE = -2135818231; /* 0x80B20009 */ +constexpr int PLAYGO_ERROR_BAD_POINTER = -2135818230; /* 0x80B2000A */ +constexpr int PLAYGO_ERROR_BAD_SIZE = -2135818229; /* 0x80B2000B */ +constexpr int PLAYGO_ERROR_BAD_CHUNK_ID = -2135818228; /* 0x80B2000C */ +constexpr int PLAYGO_ERROR_BAD_SPEED = -2135818227; /* 0x80B2000D */ +constexpr int PLAYGO_ERROR_NOT_SUPPORT_PLAYGO = -2135818226; /* 0x80B2000E */ +constexpr int PLAYGO_ERROR_EPERM = -2135818225; /* 0x80B2000F */ +constexpr int PLAYGO_ERROR_BAD_LOCUS = -2135818224; /* 0x80B20010 */ +constexpr int PLAYGO_ERROR_NEED_DATA_DISC = -2135818223; /* 0x80B20011 */ + +} // namespace PlayGo + +namespace UserService { + +constexpr int USER_SERVICE_ERROR_INTERNAL = -2137653247; /* 0x80960001 */ +constexpr int USER_SERVICE_ERROR_NOT_INITIALIZED = -2137653246; /* 0x80960002 */ +constexpr int USER_SERVICE_ERROR_ALREADY_INITIALIZED = -2137653245; /* 0x80960003 */ +constexpr int USER_SERVICE_ERROR_NO_MEMORY = -2137653244; /* 0x80960004 */ +constexpr int USER_SERVICE_ERROR_INVALID_ARGUMENT = -2137653243; /* 0x80960005 */ +constexpr int USER_SERVICE_ERROR_OPERATION_NOT_SUPPORTED = -2137653242; /* 0x80960006 */ +constexpr int USER_SERVICE_ERROR_NO_EVENT = -2137653241; /* 0x80960007 */ +constexpr int USER_SERVICE_ERROR_NOT_LOGGED_IN = -2137653239; /* 0x80960009 */ +constexpr int USER_SERVICE_ERROR_BUFFER_TOO_SHORT = -2137653238; /* 0x8096000A */ + +} // namespace UserService + } // namespace Kyty::Libs #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/include/Emulator/Libs/Libs.h b/source/emulator/include/Emulator/Libs/Libs.h index 299dd83..bfa8baa 100644 --- a/source/emulator/include/Emulator/Libs/Libs.h +++ b/source/emulator/include/Emulator/Libs/Libs.h @@ -18,9 +18,9 @@ #define LIB_DEFINE(name) void name(Loader::SymbolDatabase* s) // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define LIB_NAME(l, m) \ - static thread_local bool PRINT_NAME_ENABLED = true; \ - static constexpr char g_library[] = l; \ - static constexpr char g_module[] = m; + [[maybe_unused]] static thread_local bool PRINT_NAME_ENABLED = true; \ + static constexpr char g_library[] = l; \ + static constexpr char g_module[] = m; // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define LIB_VERSION(l, lv, m, mv1, mv2) \ LIB_NAME(l, m); \ @@ -65,8 +65,11 @@ #define PRINT_NAME() \ if (PRINT_NAME_ENABLED) \ { \ - Kyty::printf(FG_CYAN "[%d][%s] %s::%s::%s()" DEFAULT "\n", Core::Thread::GetThreadIdUnique(), \ - Loader::Timer::GetTime().ToString("HH24:MI:SS.FFF").C_Str(), g_library, g_module, __func__); \ + if (Kyty::Log::GetDirection() != Kyty::Log::Direction::Silent) \ + { \ + Kyty::printf(FG_CYAN "[%d][%s] %s::%s::%s()" DEFAULT "\n", Core::Thread::GetThreadIdUnique(), \ + Loader::Timer::GetTime().ToString("HH24:MI:SS.FFF").C_Str(), g_library, g_module, __func__); \ + } \ } namespace Kyty { diff --git a/source/emulator/include/Emulator/Log.h b/source/emulator/include/Emulator/Log.h index d605edf..11b4d08 100644 --- a/source/emulator/include/Emulator/Log.h +++ b/source/emulator/include/Emulator/Log.h @@ -68,8 +68,9 @@ enum class Direction File }; -void SetDirection(Direction dir); -void SetOutputFile(const String& file_name, Core::File::Encoding enc = Core::File::Encoding::Utf8); +Direction GetDirection(); +void SetDirection(Direction dir); +void SetOutputFile(const String& file_name, Core::File::Encoding enc = Core::File::Encoding::Utf8); bool IsColoredPrintf(); String RemoveColors(const String& str); diff --git a/source/emulator/include/Emulator/Network.h b/source/emulator/include/Emulator/Network.h new file mode 100644 index 0000000..39e4941 --- /dev/null +++ b/source/emulator/include/Emulator/Network.h @@ -0,0 +1,94 @@ +#ifndef EMULATOR_INCLUDE_EMULATOR_NETWORK_H_ +#define EMULATOR_INCLUDE_EMULATOR_NETWORK_H_ + +#include "Kyty/Core/Common.h" +#include "Kyty/Core/Subsystems.h" + +#include "Emulator/Common.h" + +#ifdef KYTY_EMU_ENABLED + +namespace Kyty::Libs::Network { + +KYTY_SUBSYSTEM_DEFINE(Network); + +namespace Net { + +struct NetEtherAddr; + +int KYTY_SYSV_ABI NetInit(); +int KYTY_SYSV_ABI NetTerm(); +int KYTY_SYSV_ABI NetPoolCreate(const char* name, int size, int flags); +int KYTY_SYSV_ABI NetPoolDestroy(int memid); +int KYTY_SYSV_ABI NetInetPton(int af, const char* src, void* dst); +int KYTY_SYSV_ABI NetEtherNtostr(const NetEtherAddr* n, char* str, size_t len); +int KYTY_SYSV_ABI NetGetMacAddress(NetEtherAddr* addr, int flags); + +} // namespace Net + +namespace Ssl { + +int KYTY_SYSV_ABI SslInit(uint64_t pool_size); +int KYTY_SYSV_ABI SslTerm(int ssl_ctx_id); + +} // namespace Ssl + +namespace Http { + +int KYTY_SYSV_ABI HttpInit(int memid, int ssl_ctx_id, uint64_t pool_size); +int KYTY_SYSV_ABI HttpTerm(int http_ctx_id); +int KYTY_SYSV_ABI HttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver, int is_auto_proxy_conf); +int KYTY_SYSV_ABI HttpDeleteTemplate(int tmpl_id); + +} // namespace Http + +namespace NetCtl { + +struct NetCtlNatInfo; +union NetCtlInfo; + +using NetCtlCallback = void (*)(int, void*); + +int KYTY_SYSV_ABI NetCtlInit(); +void KYTY_SYSV_ABI NetCtlTerm(); +int KYTY_SYSV_ABI NetCtlGetNatInfo(NetCtlNatInfo* nat_info); +int KYTY_SYSV_ABI NetCtlCheckCallback(); +int KYTY_SYSV_ABI NetCtlGetState(int* state); +int KYTY_SYSV_ABI NetCtlRegisterCallback(NetCtlCallback func, void* arg, int* cid); +int KYTY_SYSV_ABI NetCtlGetInfo(int code, NetCtlInfo* info); + +} // namespace NetCtl + +namespace NpManager { + +struct NpTitleId; +struct NpTitleSecret; +struct NpContentRestriction; + +int KYTY_SYSV_ABI NpCheckCallback(); +int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret); +int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restriction); +int KYTY_SYSV_ABI NpRegisterStateCallback(void* callback, void* userdata); +void KYTY_SYSV_ABI NpRegisterGamePresenceCallback(void* callback, void* userdata); +int KYTY_SYSV_ABI NpRegisterPlusEventCallback(void* callback, void* userdata); + +} // namespace NpManager + +namespace NpTrophy { + +int KYTY_SYSV_ABI NpTrophyCreateHandle(int* handle); + +} // namespace NpTrophy + +namespace NpWebApi { + +int KYTY_SYSV_ABI NpWebApiInitialize(int http_ctx_id, size_t pool_size); +int KYTY_SYSV_ABI NpWebApiTerminate(int lib_ctx_id); + +} // namespace NpWebApi + +} // namespace Kyty::Libs::Network + +#endif // KYTY_EMU_ENABLED + +#endif /* EMULATOR_INCLUDE_EMULATOR_NETWORK_H_ */ diff --git a/source/emulator/include/Emulator/RuntimeLinker.h b/source/emulator/include/Emulator/RuntimeLinker.h index 6ccd3c6..9f140df 100644 --- a/source/emulator/include/Emulator/RuntimeLinker.h +++ b/source/emulator/include/Emulator/RuntimeLinker.h @@ -134,6 +134,7 @@ public: void DbgDump(const String& folder); Program* LoadProgram(const String& elf_name); + void SaveMainProgram(const String& elf_name); void UnloadProgram(Program* program); [[nodiscard]] uint64_t GetEntry(); diff --git a/source/emulator/lua/ps4.lua b/source/emulator/lua/ps4.lua index 1e2db92..55dfa04 100644 --- a/source/emulator/lua/ps4.lua +++ b/source/emulator/lua/ps4.lua @@ -24,15 +24,20 @@ kyty_load_elf('/app0/main.elf'); kyty_load_elf('/app0/sce_module/libc.prx', 0); kyty_load_elf('/app0/sce_module/libSceFios2.prx', 0); +kyty_load_symbols('libAudio_1'); kyty_load_symbols('libc_internal_1'); -kyty_load_symbols('libkernel_1'); -kyty_load_symbols('libVideoOut_1'); -kyty_load_symbols('libSysmodule_1'); -kyty_load_symbols('libDiscMap_1'); kyty_load_symbols('libDebug_1'); +kyty_load_symbols('libDialog_1'); +kyty_load_symbols('libDiscMap_1'); kyty_load_symbols('libGraphicsDriver_1'); -kyty_load_symbols('libUserService_1'); +kyty_load_symbols('libkernel_1'); +kyty_load_symbols('libNet_1'); kyty_load_symbols('libPad_1'); +kyty_load_symbols('libPlayGo_1'); +kyty_load_symbols('libSysmodule_1'); +kyty_load_symbols('libSystemService_1'); +kyty_load_symbols('libUserService_1'); +kyty_load_symbols('libVideoOut_1'); kyty_execute(); diff --git a/source/emulator/src/Audio.cpp b/source/emulator/src/Audio.cpp new file mode 100644 index 0000000..1344861 --- /dev/null +++ b/source/emulator/src/Audio.cpp @@ -0,0 +1,59 @@ +#include "Emulator/Audio.h" + +#include "Kyty/Core/Common.h" +#include "Kyty/Core/DbgAssert.h" +#include "Kyty/Core/String.h" +#include "Kyty/Core/Threads.h" + +#include "Emulator/Libs/Errno.h" +#include "Emulator/Libs/Libs.h" + +#ifdef KYTY_EMU_ENABLED + +namespace Kyty::Libs::Audio { + +class Audio +{ +public: + Audio() = default; + virtual ~Audio() = default; + + KYTY_CLASS_NO_COPY(Audio); + +private: + Core::Mutex m_mutex; +}; + +static Audio* g_audio = nullptr; + +KYTY_SUBSYSTEM_INIT(Audio) +{ + EXIT_IF(g_audio != nullptr); + + g_audio = new Audio; +} + +KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Audio) {} + +KYTY_SUBSYSTEM_DESTROY(Audio) {} + +namespace VoiceQoS { + +LIB_NAME("VoiceQoS", "VoiceQoS"); + +int KYTY_SYSV_ABI VoiceQoSInit(void* mem_block, uint32_t mem_size, int32_t app_type) +{ + PRINT_NAME(); + + printf("\t mem_block = %016" PRIx64 "\n", reinterpret_cast(mem_block)); + printf("\t mem_size = %" PRIu32 "\n", mem_size); + printf("\t app_type = %" PRId32 "\n", app_type); + + return OK; +} + +} // namespace VoiceQoS + +} // namespace Kyty::Libs::Audio + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Dialog.cpp b/source/emulator/src/Dialog.cpp new file mode 100644 index 0000000..f5f20ac --- /dev/null +++ b/source/emulator/src/Dialog.cpp @@ -0,0 +1,28 @@ +#include "Emulator/Dialog.h" + +#include "Kyty/Core/String.h" + +#include "Emulator/Libs/Errno.h" +#include "Emulator/Libs/Libs.h" + +#ifdef KYTY_EMU_ENABLED + +// NOLINTNEXTLINE(modernize-concat-nested-namespaces) +namespace Kyty::Libs::Dialog { + +namespace CommonDialog { + +LIB_NAME("CommonDialog", "CommonDialog"); + +int KYTY_SYSV_ABI CommonDialogInitialize() +{ + PRINT_NAME(); + + return OK; +} + +} // namespace CommonDialog + +} // namespace Kyty::Libs::Dialog + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Elf.cpp b/source/emulator/src/Elf.cpp index fd926c9..004dabb 100644 --- a/source/emulator/src/Elf.cpp +++ b/source/emulator/src/Elf.cpp @@ -44,6 +44,17 @@ static Elf64_Ehdr* load_ehdr_64(Core::File& f) return ehdr; } +static void save_ehdr_64(Core::File& f, const Elf64_Ehdr* ehdr) +{ + EXIT_IF(ehdr == nullptr); + + uint32_t bytes_written = 0; + + f.Write(ehdr, sizeof(Elf64_Ehdr), &bytes_written); + + EXIT_IF(bytes_written == 0); +} + static Elf64_Phdr* load_phdr_64(Core::File& f, uint64_t offset, Elf64_Half num) { auto* phdr = new Elf64_Phdr[num]; @@ -54,6 +65,18 @@ static Elf64_Phdr* load_phdr_64(Core::File& f, uint64_t offset, Elf64_Half num) return phdr; } +static void save_phdr_64(Core::File& f, uint64_t offset, Elf64_Half num, const Elf64_Phdr* phdr) +{ + EXIT_IF(phdr == nullptr); + + uint32_t bytes_written = 0; + + f.Seek(offset); + f.Write(phdr, sizeof(Elf64_Phdr) * num, &bytes_written); + + EXIT_IF(bytes_written == 0); +} + static Elf64_Shdr* load_shdr_64(Core::File& f, uint64_t offset, Elf64_Half num) { if (num == 0) @@ -69,6 +92,23 @@ static Elf64_Shdr* load_shdr_64(Core::File& f, uint64_t offset, Elf64_Half num) return shdr; } +static void save_shdr_64(Core::File& f, uint64_t offset, Elf64_Half num, const Elf64_Shdr* shdr) +{ + if (num == 0) + { + return; + } + + EXIT_IF(shdr == nullptr); + + uint32_t bytes_written = 0; + + f.Seek(offset); + f.Write(shdr, sizeof(Elf64_Shdr) * num, &bytes_written); + + EXIT_IF(bytes_written == 0); +} + static void* load_dynamic_64(Elf64* f, uint64_t offset, uint64_t size) { void* dynamic_data = new uint8_t[size]; @@ -599,6 +639,72 @@ void Elf64::Open(const String& file_name) } } +void Elf64::Save(const String& file_name) +{ + EXIT_IF(!IsValid()); + + if (IsValid()) + { + Core::File f; + f.Create(file_name); + + if (f.IsInvalid()) + { + EXIT("Can't create %s\n", file_name.C_Str()); + } + + save_ehdr_64(f, m_ehdr); + + save_phdr_64(f, m_ehdr->e_phoff, m_ehdr->e_phnum, m_phdr); + save_shdr_64(f, m_ehdr->e_shoff, m_ehdr->e_shnum, m_shdr); + + for (uint16_t i = 0; i < m_ehdr->e_phnum; i++) + { + if (m_phdr[i].p_filesz == 0u) + { + continue; + } + + auto* buf = new char[static_cast(m_phdr[i].p_filesz)]; + + LoadSegment(reinterpret_cast(buf), m_phdr[i].p_offset, m_phdr[i].p_filesz); + + uint32_t bytes_written = 0; + + f.Seek(m_phdr[i].p_offset); + f.Write(buf, static_cast(m_phdr[i].p_filesz), &bytes_written); + + EXIT_IF(bytes_written == 0); + + delete[] buf; + } + + for (uint16_t i = 0; i < m_ehdr->e_shnum; i++) + { + if (m_shdr[i].sh_size == 0u) + { + continue; + } + + auto* buf = new char[static_cast(m_shdr[i].sh_size)]; + + m_f->Seek(m_shdr[i].sh_offset); + m_f->Read(buf, static_cast(m_shdr[i].sh_size)); + + uint32_t bytes_written = 0; + + f.Seek(m_shdr[i].sh_offset); + f.Write(buf, static_cast(m_shdr[i].sh_size), &bytes_written); + + EXIT_IF(bytes_written == 0); + + delete[] buf; + } + + f.Close(); + } +} + } // namespace Kyty::Loader #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Graphics/GraphicsRender.cpp b/source/emulator/src/Graphics/GraphicsRender.cpp index 3799e33..51776b1 100644 --- a/source/emulator/src/Graphics/GraphicsRender.cpp +++ b/source/emulator/src/Graphics/GraphicsRender.cpp @@ -530,9 +530,9 @@ static void rt_check(const HW::RenderTarget& rt) // EXIT_NOT_IMPLEMENTED(rt.dcc_max_uncompressed_block_size != 0x00000002); EXIT_NOT_IMPLEMENTED(rt.dcc.max_compressed_block_size != 0x00000000); EXIT_NOT_IMPLEMENTED(rt.dcc.min_compressed_block_size != 0x00000000); - EXIT_NOT_IMPLEMENTED(rt.dcc.color_transform != 0x00000000); + // EXIT_NOT_IMPLEMENTED(rt.dcc.color_transform != 0x00000000); EXIT_NOT_IMPLEMENTED(rt.dcc.enable_overwrite_combiner != false); - EXIT_NOT_IMPLEMENTED(rt.dcc.force_independent_blocks != false); + // EXIT_NOT_IMPLEMENTED(rt.dcc.force_independent_blocks != false); EXIT_NOT_IMPLEMENTED(rt.cmask.addr != 0x0000000000000000); EXIT_NOT_IMPLEMENTED(rt.cmask_slice.slice_minus1 != 0x00000000); EXIT_NOT_IMPLEMENTED(rt.fmask.addr != 0x0000000000000000); @@ -733,7 +733,7 @@ static void mc_print(const char* func, const HW::ModeControl& c) static void mc_check(const HW::ModeControl& c) { - EXIT_NOT_IMPLEMENTED(c.cull_front != false); + // EXIT_NOT_IMPLEMENTED(c.cull_front != false); // EXIT_NOT_IMPLEMENTED(c.cull_back != false); EXIT_NOT_IMPLEMENTED(c.face != false); EXIT_NOT_IMPLEMENTED(c.poly_mode != 0); @@ -771,10 +771,10 @@ static void bc_check(const HW::BlendControl& c, const HW::BlendColor& color, con // EXIT_NOT_IMPLEMENTED(c.color_srcblend != 0); EXIT_NOT_IMPLEMENTED(c.color_comb_fcn != 0); // EXIT_NOT_IMPLEMENTED(c.color_destblend != 0); - EXIT_NOT_IMPLEMENTED(c.alpha_srcblend != 0); + // EXIT_NOT_IMPLEMENTED(c.alpha_srcblend != 0); EXIT_NOT_IMPLEMENTED(c.alpha_comb_fcn != 0); - EXIT_NOT_IMPLEMENTED(c.alpha_destblend != 0); - EXIT_NOT_IMPLEMENTED(c.separate_alpha_blend != false); + // 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); @@ -2863,7 +2863,7 @@ VulkanDescriptorSet* DescriptorCache::GetDescriptor(Stage stage, VulkanBuffer** gds_buffer_info[i].range = VK_WHOLE_SIZE; } - int binding_num = 0; + uint32_t binding_num = 0; constexpr uint32_t B_MAX = 5; @@ -3321,6 +3321,23 @@ void GraphicsRenderRenderTextureBarrier(CommandBuffer* buffer, uint64_t vaddr, u } } +void GraphicsRenderDepthStencilBarrier(CommandBuffer* buffer, uint64_t vaddr, uint64_t size) +{ + EXIT_IF(buffer == nullptr); + EXIT_IF(buffer->IsInvalid()); + + Core::LockGuard lock(g_render_ctx->GetMutex()); + + auto* vk_buffer = buffer->GetPool()->buffers[buffer->GetIndex()]; + + auto images = FindDepthStencil(vaddr, size, false); + + for (auto* image: images) + { + GraphicsRenderDepthStencilBarrier(vk_buffer, image); + } +} + // NOLINTNEXTLINE(readability-function-cognitive-complexity) static void FindRenderDepthInfo(CommandBuffer* /*buffer*/, const HW::HardwareContext& hw, RenderDepthInfo* r) { @@ -3500,6 +3517,8 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext uint32_t format = 0; bool render_to_texture = false; + auto video_image = VideoOut::VideoOutGetImage(rt.base.addr); + if (rt.attrib.tile_mode == 0x8) { tile = false; @@ -3507,7 +3526,7 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext { tile = true; - if (rt.info.format == 0xa && rt.info.channel_type == 0x0 && rt.info.channel_order == 0x0 && rt.size.width == rt.size.height) + if (rt.info.format == 0xa && rt.info.channel_type == 0x0 && (rt.info.channel_order == 0x0 || rt.info.channel_order == 0x1)) { render_to_texture = true; } @@ -3520,26 +3539,38 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext EXIT("unknown tile mode: %u\n", rt.attrib.tile_mode); } + if (render_to_texture && video_image.image != nullptr) + { + render_to_texture = false; + } + if (render_to_texture) { + RenderTextureFormat rt_format = RenderTextureFormat::Unknown; + if (rt.info.format == 0xa && rt.info.channel_type == 0x0 && rt.info.channel_order == 0x0) { - // Render to texture - RenderTextureObject vulkan_buffer_info(RenderTextureFormat::R8G8B8A8Unorm, width, height, tile, rt.info.neo_mode, pitch); - auto* buffer_vulkan = static_cast( - Graphics::GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), buffer, rt.base.addr, size, vulkan_buffer_info)); - EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr); - r->type = RenderColorType::RenderTexture; - r->base_addr = rt.base.addr; - r->vulkan_buffer = buffer_vulkan; - r->buffer_size = size; + rt_format = RenderTextureFormat::R8G8B8A8Unorm; + } else if (rt.info.format == 0xa && rt.info.channel_type == 0x0 && rt.info.channel_order == 0x1) + { + rt_format = RenderTextureFormat::B8G8R8A8Unorm; } else { EXIT("unknown format"); } + + // Render to texture + RenderTextureObject vulkan_buffer_info(rt_format, width, height, tile, rt.info.neo_mode, pitch); + auto* buffer_vulkan = static_cast( + Graphics::GpuMemoryCreateObject(g_render_ctx->GetGraphicCtx(), buffer, rt.base.addr, size, vulkan_buffer_info)); + EXIT_NOT_IMPLEMENTED(buffer_vulkan == nullptr); + r->type = RenderColorType::RenderTexture; + r->base_addr = rt.base.addr; + r->vulkan_buffer = buffer_vulkan; + r->buffer_size = size; } else { - if (rt.info.format == 0xa && rt.info.channel_type == 0x6 && rt.info.channel_order == 0x1) + if (rt.info.format == 0xa && (rt.info.channel_type == 0x6 || rt.info.channel_type == 0x0) && rt.info.channel_order == 0x1) { format = 0x80000000; } else @@ -3547,7 +3578,6 @@ static void FindRenderColorInfo(CommandBuffer* buffer, const HW::HardwareContext EXIT("unknown format"); } - auto video_image = VideoOut::VideoOutGetImage(rt.base.addr); if (video_image.image == nullptr) { // Offscreen buffer @@ -3679,7 +3709,7 @@ static void PrepareTextures(CommandBuffer* buffer, const ShaderTextureResources& EXIT_NOT_IMPLEMENTED(r.Base() == 0); EXIT_NOT_IMPLEMENTED(r.MinLod() != 0); - EXIT_NOT_IMPLEMENTED(r.Dfmt() != 10 && r.Dfmt() != 37 && r.Dfmt() != 4); + EXIT_NOT_IMPLEMENTED(r.Dfmt() != 1 && r.Dfmt() != 10 && r.Dfmt() != 37 && r.Dfmt() != 4); EXIT_NOT_IMPLEMENTED(r.Nfmt() != 9 && r.Nfmt() != 0 && r.Nfmt() != 7); // EXIT_NOT_IMPLEMENTED(r.Width() != 511); // EXIT_NOT_IMPLEMENTED(r.Height() != 511); @@ -3815,9 +3845,9 @@ static void PrepareSamplers(const ShaderSamplerResources& samplers, uint64_t* sa { auto r = samplers.samplers[i]; - EXIT_NOT_IMPLEMENTED(r.ClampX() != 0); - EXIT_NOT_IMPLEMENTED(r.ClampY() != 0); - EXIT_NOT_IMPLEMENTED(r.ClampZ() != 0); + // EXIT_NOT_IMPLEMENTED(r.ClampX() != 0); + // EXIT_NOT_IMPLEMENTED(r.ClampY() != 0); + // EXIT_NOT_IMPLEMENTED(r.ClampZ() != 0); // EXIT_NOT_IMPLEMENTED(r.MaxAnisoRatio() != 0); EXIT_NOT_IMPLEMENTED(r.DepthCompareFunc() != 0); EXIT_NOT_IMPLEMENTED(r.ForceUnormCoords() != false); @@ -3832,7 +3862,7 @@ static void PrepareSamplers(const ShaderSamplerResources& samplers, uint64_t* sa // EXIT_NOT_IMPLEMENTED(r.MaxLod() != 4095); EXIT_NOT_IMPLEMENTED(r.PerfMip() != 0); EXIT_NOT_IMPLEMENTED(r.PerfZ() != 0); - EXIT_NOT_IMPLEMENTED(r.LodBias() != 0); + // EXIT_NOT_IMPLEMENTED(r.LodBias() != 0); EXIT_NOT_IMPLEMENTED(r.LodBiasSec() != 0); // EXIT_NOT_IMPLEMENTED(r.XyMagFilter() != 1); // EXIT_NOT_IMPLEMENTED(r.XyMinFilter() != 1); @@ -4184,9 +4214,9 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx switch (ucfg->GetPrimType()) { - case 4: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; break; - case 17: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; break; - case 19: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; break; + case 4: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; break; // kPrimitiveTypeTriList + case 17: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; break; // kPrimitiveTypeRectList + case 19: topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; break; // kPrimitiveTypeQuadList default: EXIT("unknown primitive type: %u\n", ucfg->GetPrimType()); } @@ -4239,8 +4269,11 @@ void GraphicsRenderDrawIndexAuto(CommandBuffer* buffer, HW::HardwareContext* ctx vkCmdDraw(vk_buffer, 4, 1, 0, 0); break; case 19: - EXIT_NOT_IMPLEMENTED(index_count != 4); - vkCmdDraw(vk_buffer, 4, 1, 0, 0); + EXIT_NOT_IMPLEMENTED((index_count & 0x3u) != 0); + for (uint32_t i = 0; i < index_count; i += 4) + { + vkCmdDraw(vk_buffer, 4, 1, i, 0); + } break; default: EXIT("unknown primitive type: %u\n", ucfg->GetPrimType()); } diff --git a/source/emulator/src/Graphics/GraphicsRun.cpp b/source/emulator/src/Graphics/GraphicsRun.cpp index 725447b..1f0225b 100644 --- a/source/emulator/src/Graphics/GraphicsRun.cpp +++ b/source/emulator/src/Graphics/GraphicsRun.cpp @@ -72,6 +72,7 @@ public: void WriteBack(); void MemoryBarrier(); void RenderTextureBarrier(uint64_t vaddr, uint64_t size); + void DepthStencilBarrier(uint64_t vaddr, uint64_t size); void DispatchDirect(uint32_t thread_group_x, uint32_t thread_group_y, uint32_t thread_group_z, uint32_t mode); void WaitFlipDone(uint32_t video_out_handle, uint32_t display_buffer_index); void TriggerEvent(uint32_t event_type, uint32_t event_index); @@ -1115,6 +1116,15 @@ void CommandProcessor::RenderTextureBarrier(uint64_t vaddr, uint64_t size) GraphicsRenderRenderTextureBarrier(m_buffer[m_current_buffer], vaddr, size); } +void CommandProcessor::DepthStencilBarrier(uint64_t vaddr, uint64_t size) +{ + Core::LockGuard lock(m_mutex); + + EXIT_IF(m_current_buffer < 0 || m_current_buffer >= VK_BUFFERS_NUM); + + GraphicsRenderDepthStencilBarrier(m_buffer[m_current_buffer], vaddr, size); +} + void CommandProcessor::TriggerEvent(uint32_t event_type, uint32_t event_index) { Core::LockGuard lock(m_mutex); @@ -1902,6 +1912,17 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_vs_shader) return 28; } +KYTY_HW_CTX_PARSER(hw_ctx_update_vs_shader) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xc01b103c); + + auto shader_modifier = buffer[0]; + + cp->GetCtx()->UpdateVsShader(reinterpret_cast(buffer + 1), shader_modifier); + + return 28; +} + KYTY_HW_CTX_PARSER(hw_ctx_set_vs_embedded) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xc01b1034); @@ -1961,6 +1982,25 @@ KYTY_HW_CTX_PARSER(hw_ctx_set_ps_shader) return 39; } +KYTY_HW_CTX_PARSER(hw_ctx_update_ps_shader) +{ + EXIT_NOT_IMPLEMENTED(cmd_id != 0xc0261040); + + HW::PsStageRegisters r {}; + + r.data_addr = (static_cast(buffer[0]) << 8u) | (static_cast(buffer[1]) << 40u); + r.vgprs = (buffer[2] >> Pm4::SPI_SHADER_PGM_RSRC1_PS_VGPRS_SHIFT) & Pm4::SPI_SHADER_PGM_RSRC1_PS_VGPRS_MASK; + r.sgprs = (buffer[2] >> Pm4::SPI_SHADER_PGM_RSRC1_PS_SGPRS_SHIFT) & Pm4::SPI_SHADER_PGM_RSRC1_PS_SGPRS_MASK; + r.scratch_en = (buffer[3] >> Pm4::SPI_SHADER_PGM_RSRC2_PS_SCRATCH_EN_SHIFT) & Pm4::SPI_SHADER_PGM_RSRC2_PS_SCRATCH_EN_MASK; + r.user_sgpr = (buffer[3] >> Pm4::SPI_SHADER_PGM_RSRC2_PS_USER_SGPR_SHIFT) & Pm4::SPI_SHADER_PGM_RSRC2_PS_USER_SGPR_MASK; + r.wave_cnt_en = (buffer[3] >> Pm4::SPI_SHADER_PGM_RSRC2_PS_WAVE_CNT_EN_SHIFT) & Pm4::SPI_SHADER_PGM_RSRC2_PS_WAVE_CNT_EN_MASK; + r.shader_z_format = buffer[4]; + + cp->GetCtx()->UpdatePsShader(&r); + + return 39; +} + KYTY_HW_CTX_PARSER(hw_ctx_set_cs_shader) { EXIT_NOT_IMPLEMENTED(cmd_id != 0xC017101C); @@ -2500,7 +2540,12 @@ KYTY_CP_OP_PARSER(cp_op_acquire_mem) // target_mask: 0x00004000 (Depth Target) // extended_action: 0x04000000 (FlushAndInvalidateDbCache) // action: 0x38 (WriteBackAndInvalidateL1andL2) - KYTY_NOT_IMPLEMENTED; + EXIT_IF(target_mask != 0x00004000); + EXIT_IF(extended_action != 0x04000000); + EXIT_IF(action != 0x38); + + cp->DepthStencilBarrier(base_lo << 8u, size_lo << 8u); + cp->WriteBack(); } break; default: @@ -2668,6 +2713,8 @@ KYTY_CP_OP_PARSER(cp_op_nop) case Pm4::R_POP_MARKER: return cp_op_pop_marker(cp, cmd_id, buffer, dw, num_dw); break; case Pm4::R_VS_EMBEDDED: return hw_ctx_set_vs_embedded(cp, cmd_id, 0, buffer, dw); break; case Pm4::R_PS_EMBEDDED: return hw_ctx_set_ps_embedded(cp, cmd_id, 0, buffer, dw); break; + case Pm4::R_VS_UPDATE: return hw_ctx_update_vs_shader(cp, cmd_id, 0, buffer, dw); break; + case Pm4::R_PS_UPDATE: return hw_ctx_update_ps_shader(cp, cmd_id, 0, buffer, dw); break; default: break; } diff --git a/source/emulator/src/Graphics/Objects/GpuMemory.cpp b/source/emulator/src/Graphics/Objects/GpuMemory.cpp index 2cd3d89..bb4fe5a 100644 --- a/source/emulator/src/Graphics/Objects/GpuMemory.cpp +++ b/source/emulator/src/Graphics/Objects/GpuMemory.cpp @@ -102,7 +102,7 @@ public: static bool Enabled() { - static const bool enabled = !Core::dbg_is_debugger_present(); + static const bool enabled = false; // !Core::dbg_is_debugger_present(); return enabled; } diff --git a/source/emulator/src/Graphics/Objects/RenderTexture.cpp b/source/emulator/src/Graphics/Objects/RenderTexture.cpp index 3f1b7b4..434360e 100644 --- a/source/emulator/src/Graphics/Objects/RenderTexture.cpp +++ b/source/emulator/src/Graphics/Objects/RenderTexture.cpp @@ -165,6 +165,7 @@ static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint switch (pixel_format) // NOLINT { case static_cast(RenderTextureFormat::R8G8B8A8Unorm): vk_format = VK_FORMAT_R8G8B8A8_UNORM; break; + case static_cast(RenderTextureFormat::B8G8R8A8Unorm): vk_format = VK_FORMAT_B8G8R8A8_UNORM; break; default: EXIT("unknown format: %" PRIu64 "\n", pixel_format); } @@ -267,6 +268,7 @@ static void* create2_func(GraphicContext* ctx, CommandBuffer* buffer, const uint switch (pixel_format) // NOLINT { case static_cast(RenderTextureFormat::R8G8B8A8Unorm): vk_format = VK_FORMAT_R8G8B8A8_UNORM; break; + case static_cast(RenderTextureFormat::B8G8R8A8Unorm): vk_format = VK_FORMAT_B8G8R8A8_UNORM; break; default: EXIT("unknown format: %" PRIu64 "\n", pixel_format); } diff --git a/source/emulator/src/Graphics/Objects/Texture.cpp b/source/emulator/src/Graphics/Objects/Texture.cpp index ecd8916..177410b 100644 --- a/source/emulator/src/Graphics/Objects/Texture.cpp +++ b/source/emulator/src/Graphics/Objects/Texture.cpp @@ -26,6 +26,10 @@ static VkFormat get_texture_format(uint32_t dfmt, uint32_t nfmt) { return VK_FORMAT_R8G8B8A8_UNORM; } + if (nfmt == 0 && dfmt == 1) + { + return VK_FORMAT_R8_UNORM; + } if (nfmt == 9 && dfmt == 37) { return VK_FORMAT_BC3_SRGB_BLOCK; diff --git a/source/emulator/src/Graphics/Objects/VertexBuffer.cpp b/source/emulator/src/Graphics/Objects/VertexBuffer.cpp index 9741282..4e46f31 100644 --- a/source/emulator/src/Graphics/Objects/VertexBuffer.cpp +++ b/source/emulator/src/Graphics/Objects/VertexBuffer.cpp @@ -12,7 +12,34 @@ namespace Kyty::Libs::Graphics { -static void* create_func(GraphicContext* ctx, const uint64_t* /*params*/, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, +static void update_func(GraphicContext* ctx, const uint64_t* /*params*/, void* obj, const uint64_t* vaddr, const uint64_t* size, + int vaddr_num) +{ + KYTY_PROFILER_BLOCK("VertexBufferGpuObject::update_func"); + + EXIT_IF(vaddr_num != 1 || size == nullptr || vaddr == nullptr || *vaddr == 0); + EXIT_IF(obj == nullptr); + + auto* vk_obj = static_cast(obj); + + VulkanBuffer staging_buffer {}; + staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; + staging_buffer.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; + + VulkanCreateBuffer(ctx, *size, &staging_buffer); + EXIT_NOT_IMPLEMENTED(staging_buffer.buffer == nullptr); + + void* data = nullptr; + VulkanMapMemory(ctx, &staging_buffer.memory, &data); + memcpy(data, reinterpret_cast(*vaddr), *size); + VulkanUnmapMemory(ctx, &staging_buffer.memory); + + UtilCopyBuffer(&staging_buffer, vk_obj, *size); + + VulkanDeleteBuffer(ctx, &staging_buffer); +} + +static void* create_func(GraphicContext* ctx, const uint64_t* params, const uint64_t* vaddr, const uint64_t* size, int vaddr_num, VulkanMemory* mem) { KYTY_PROFILER_BLOCK("VertexBufferGpuObject::Create"); @@ -30,35 +57,11 @@ static void* create_func(GraphicContext* ctx, const uint64_t* /*params*/, const VulkanCreateBuffer(ctx, *size, vk_obj); EXIT_NOT_IMPLEMENTED(vk_obj->buffer == nullptr); - VulkanBuffer staging_buffer {}; - staging_buffer.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - staging_buffer.memory.property = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - - VulkanCreateBuffer(ctx, *size, &staging_buffer); - EXIT_NOT_IMPLEMENTED(staging_buffer.buffer == nullptr); - - void* data = nullptr; - // vkMapMemory(ctx->device, staging_buffer.memory.memory, staging_buffer.memory.offset, *size, 0, &data); - VulkanMapMemory(ctx, &staging_buffer.memory, &data); - memcpy(data, reinterpret_cast(*vaddr), *size); - // vkUnmapMemory(ctx->device, staging_buffer.memory.memory); - VulkanUnmapMemory(ctx, &staging_buffer.memory); - - UtilCopyBuffer(&staging_buffer, vk_obj, *size); - - VulkanDeleteBuffer(ctx, &staging_buffer); + update_func(ctx, params, vk_obj, vaddr, size, vaddr_num); return vk_obj; } -static void update_func(GraphicContext* /*ctx*/, const uint64_t* /*params*/, void* /*obj*/, const uint64_t* /*vaddr*/, - const uint64_t* /*size*/, int /*vaddr_num*/) -{ - KYTY_PROFILER_BLOCK("VertexBufferGpuObject::update_func"); - - KYTY_NOT_IMPLEMENTED; -} - static void delete_func(GraphicContext* ctx, void* obj, VulkanMemory* /*mem*/) { KYTY_PROFILER_BLOCK("VertexBufferGpuObject::delete_func"); diff --git a/source/emulator/src/Graphics/Shader.cpp b/source/emulator/src/Graphics/Shader.cpp index c7a4134..d3515a0 100644 --- a/source/emulator/src/Graphics/Shader.cpp +++ b/source/emulator/src/Graphics/Shader.cpp @@ -212,7 +212,8 @@ static String dbg_fmt_to_str(const ShaderInstruction& inst) case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxen: return U"Vdata4VaddrSvSoffsIdxen"; break; case ShaderInstructionFormat::Vdata4VaddrSvSoffsIdxenFloat4: return U"Vdata4VaddrSvSoffsIdxenFloat4"; break; case ShaderInstructionFormat::Vdata4Vaddr2SvSoffsOffenIdxenFloat4: return U"Vdata4Vaddr2SvSoffsOffenIdxenFloat4"; break; - case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata4Vaddr3StSsDmask7"; break; + case ShaderInstructionFormat::Vdata1Vaddr3StSsDmask1: return U"Vdata1Vaddr3StSsDmask1"; break; + case ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7: return U"Vdata3Vaddr3StSsDmask7"; break; case ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF: return U"Vdata4Vaddr3StSsDmaskF"; break; case ShaderInstructionFormat::Vdata4Vaddr3StDmaskF: return U"Vdata4Vaddr3StDmaskF"; break; case ShaderInstructionFormat::Vdata4Vaddr4StDmaskF: return U"Vdata4Vaddr4StDmaskF"; break; @@ -286,6 +287,7 @@ static String dbg_fmt_print(const ShaderInstruction& inst) case ShaderInstructionFormat::Compr: s = U"compr"; break; case ShaderInstructionFormat::Vm: s = U"vm"; break; case ShaderInstructionFormat::L: s = String::FromPrintf("label_%04" PRIx32, inst.pc + 4 + inst.src[0].constant.i); break; + case ShaderInstructionFormat::Dmask1: s = U"dmask:0x1"; break; case ShaderInstructionFormat::Dmask7: s = U"dmask:0x7"; break; case ShaderInstructionFormat::DmaskF: s = U"dmask:0xf"; break; case ShaderInstructionFormat::Gds: s = U"gds"; break; @@ -1532,7 +1534,7 @@ KYTY_SHADER_PARSER(shader_parse_mimg) EXIT_NOT_IMPLEMENTED(glc == 1); EXIT_NOT_IMPLEMENTED(slc == 1); EXIT_NOT_IMPLEMENTED(unrm == 1); - EXIT_NOT_IMPLEMENTED(dmask != 0xf && dmask != 0x7); + // EXIT_NOT_IMPLEMENTED(dmask != 0xf && dmask != 0x7); uint32_t size = 2; @@ -1584,14 +1586,27 @@ KYTY_SHADER_PARSER(shader_parse_mimg) inst.src[0].size = 3; inst.src[1].size = 8; inst.src[2].size = 4; - if (dmask == 0x7) + switch (dmask) { - inst.format = ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7; - inst.dst.size = 3; - } else if (dmask == 0xf) - { - inst.format = ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF; - inst.dst.size = 4; + case 0x1: + { + inst.format = ShaderInstructionFormat::Vdata1Vaddr3StSsDmask1; + inst.dst.size = 1; + break; + } + case 0x7: + { + inst.format = ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7; + inst.dst.size = 3; + break; + } + case 0xf: + { + inst.format = ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF; + inst.dst.size = 4; + break; + } + default:; } break; default: printf("%s", dst->DbgDump().C_Str()); EXIT("unknown mimg opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc); @@ -1600,7 +1615,7 @@ KYTY_SHADER_PARSER(shader_parse_mimg) if (inst.format == ShaderInstructionFormat::Unknown) { printf("%s", dst->DbgDump().C_Str()); - EXIT("unknown mimg format for opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 "\n", opcode, pc) + EXIT("unknown mimg format for opcode: 0x%02" PRIx32 " at addr 0x%08" PRIx32 ", dmask: 0x%" PRIx32 "\n", opcode, pc, dmask); } dst->GetInstructions().Add(inst); diff --git a/source/emulator/src/Graphics/ShaderSpirv.cpp b/source/emulator/src/Graphics/ShaderSpirv.cpp index 68829fc..282c374 100644 --- a/source/emulator/src/Graphics/ShaderSpirv.cpp +++ b/source/emulator/src/Graphics/ShaderSpirv.cpp @@ -2217,6 +2217,61 @@ KYTY_RECOMPILER_FUNC(Recompile_Exp_Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done) return true; } +KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata1Vaddr3StSsDmask1) +{ + const auto& inst = code.GetInstructions().At(index); + const auto* bind_info = spirv->GetBindInfo(); + // const auto& bind_params = spirv->GetBindParams(); + + if (bind_info != nullptr && bind_info->textures2D.textures2d_sampled_num > 0 && bind_info->samplers.samplers_num > 0) + { + auto dst_value0 = operand_variable_to_str(inst.dst, 0); + auto src0_value0 = operand_variable_to_str(inst.src[0], 0); + auto src0_value1 = operand_variable_to_str(inst.src[0], 1); + auto src0_value2 = operand_variable_to_str(inst.src[0], 2); + auto src1_value0 = operand_variable_to_str(inst.src[1], 0); + auto src2_value0 = operand_variable_to_str(inst.src[2], 0); + + EXIT_NOT_IMPLEMENTED(dst_value0.type != SpirvType::Float); + EXIT_NOT_IMPLEMENTED(src0_value0.type != SpirvType::Float); + EXIT_NOT_IMPLEMENTED(src1_value0.type != SpirvType::Uint); + EXIT_NOT_IMPLEMENTED(src2_value0.type != SpirvType::Uint); + + // TODO() check VSKIP + // TODO() check LOD_CLAMPED + + static const char32_t* text = UR"( + %t24_ = OpLoad %uint % + %t26_ = OpAccessChain %_ptr_UniformConstant_ImageS %textures2D_S %t24_ + %t27_ = OpLoad %ImageS %t26_ + %t33_ = OpLoad %uint % + %t35_ = OpAccessChain %_ptr_UniformConstant_Sampler %samplers %t33_ + %t36_ = OpLoad %Sampler %t35_ + %t38_ = OpSampledImage %SampledImage %t27_ %t36_ + %t39_ = OpLoad %float % + %t40_ = OpLoad %float % + %t42_ = OpCompositeConstruct %v2float %t39_ %t40_ + %t43_ = OpImageSampleImplicitLod %v4float %t38_ %t42_ + OpStore %temp_v4float %t43_ + %t46_ = OpAccessChain %_ptr_Function_float %temp_v4float %uint_0 + %t47_ = OpLoad %float %t46_ + OpStore % %t47_ +)"; + *dst_source += String(text) + .ReplaceStr(U"", String::FromPrintf("%u", index)) + .ReplaceStr(U"", src0_value0.value) + .ReplaceStr(U"", src0_value1.value) + .ReplaceStr(U"", src0_value2.value) + .ReplaceStr(U"", src1_value0.value) + .ReplaceStr(U"", src2_value0.value) + .ReplaceStr(U"", dst_value0.value); + + return true; + } + + return false; +} + KYTY_RECOMPILER_FUNC(Recompile_ImageSample_Vdata3Vaddr3StSsDmask7) { const auto& inst = code.GetInstructions().At(index); @@ -4855,6 +4910,7 @@ static RecompilerFunc g_recomp_func[] = { {Recompile_Exp_Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done, ShaderInstructionType::Exp, ShaderInstructionFormat::Pos0Vsrc0Vsrc1Vsrc2Vsrc3Done, {U""}}, {Recompile_ImageLoad_Vdata4Vaddr3StDmaskF, ShaderInstructionType::ImageLoad, ShaderInstructionFormat::Vdata4Vaddr3StDmaskF, {U""}}, + {Recompile_ImageSample_Vdata1Vaddr3StSsDmask1, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata1Vaddr3StSsDmask1, {U""}}, {Recompile_ImageSample_Vdata3Vaddr3StSsDmask7, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata3Vaddr3StSsDmask7, {U""}}, {Recompile_ImageSample_Vdata4Vaddr3StSsDmaskF, ShaderInstructionType::ImageSample, ShaderInstructionFormat::Vdata4Vaddr3StSsDmaskF, {U""}}, {Recompile_ImageStore_Vdata4Vaddr3StDmaskF, ShaderInstructionType::ImageStore, ShaderInstructionFormat::Vdata4Vaddr3StDmaskF, {U""}}, diff --git a/source/emulator/src/Graphics/Tile.cpp b/source/emulator/src/Graphics/Tile.cpp index 73474b8..33de751 100644 --- a/source/emulator/src/Graphics/Tile.cpp +++ b/source/emulator/src/Graphics/Tile.cpp @@ -678,6 +678,11 @@ void TileGetTextureSize(uint32_t dfmt, uint32_t nfmt, uint32_t width, uint32_t h { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, { 4, 7, 1920, 1080, 11, 2, true, {8847360, 12124160, 1048576, 262144, 65536, 16384, 2048, 1024, 1024, 1024, 1024, }, { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, + // kDataFormatR8Unorm, 2048, 2048, kTileModeDisplay_LinearAligned + { 1, 0, 2048, 2048, 12, 8, false, {4194304, 1048576, 262144, 65536, 16384, 4096, 2048, 1024, 512, 256, 256, 256, }, + { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, + { 1, 0, 2048, 2048, 12, 8, true, {4194304, 1048576, 262144, 65536, 16384, 4096, 2048, 1024, 512, 256, 256, 256, }, + { {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, } }, // clang-format on }; diff --git a/source/emulator/src/Graphics/Window.cpp b/source/emulator/src/Graphics/Window.cpp index a107275..1ba8191 100644 --- a/source/emulator/src/Graphics/Window.cpp +++ b/source/emulator/src/Graphics/Window.cpp @@ -1434,6 +1434,13 @@ static VkPhysicalDevice VulkanFindPhysicalDevice(VkInstance instance, VkSurfaceK skip_device = true; } + if (!skip_device && + !CheckFormat(device, VK_FORMAT_R8_UNORM, true, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) + { + printf("Format VK_FORMAT_R8_UNORM cannot be used as texture\n"); + skip_device = true; + } + if (!skip_device && !CheckFormat(device, VK_FORMAT_R8G8B8A8_SRGB, true, VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT | VK_FORMAT_FEATURE_TRANSFER_DST_BIT)) { diff --git a/source/emulator/src/Kyty.cpp b/source/emulator/src/Kyty.cpp index df591c4..7aa4d3e 100644 --- a/source/emulator/src/Kyty.cpp +++ b/source/emulator/src/Kyty.cpp @@ -9,6 +9,7 @@ #include "Kyty/Core/Vector.h" #include "Kyty/Scripts/Scripts.h" +#include "Emulator/Audio.h" #include "Emulator/Common.h" #include "Emulator/Config.h" #include "Emulator/Controller.h" @@ -19,6 +20,7 @@ #include "Emulator/Kernel/Memory.h" #include "Emulator/Kernel/Pthread.h" #include "Emulator/Libs/Libs.h" +#include "Emulator/Network.h" #include "Emulator/Profiler.h" #include "Emulator/RuntimeLinker.h" #include "Emulator/Timer.h" @@ -75,31 +77,35 @@ static void Init(const Scripts::ScriptVar& cfg) auto* slist = Core::SubsystemsList::Instance(); - auto* log = Log::LogSubsystem::Instance(); - auto* core = Core::CoreSubsystem::Instance(); - auto* scripts = Scripts::ScriptsSubsystem::Instance(); + auto* audio = Libs::Audio::AudioSubsystem::Instance(); auto* config = Config::ConfigSubsystem::Instance(); - auto* pthread = Libs::LibKernel::PthreadSubsystem::Instance(); - auto* timer = Loader::Timer::TimerSubsystem::Instance(); - auto* file_system = Libs::LibKernel::FileSystem::FileSystemSubsystem::Instance(); - auto* memory = Libs::LibKernel::Memory::MemorySubsystem::Instance(); - auto* graphics = Libs::Graphics::GraphicsSubsystem::Instance(); - auto* profiler = Profiler::ProfilerSubsystem::Instance(); auto* controller = Libs::Controller::ControllerSubsystem::Instance(); + auto* core = Core::CoreSubsystem::Instance(); + auto* file_system = Libs::LibKernel::FileSystem::FileSystemSubsystem::Instance(); + auto* graphics = Libs::Graphics::GraphicsSubsystem::Instance(); + auto* log = Log::LogSubsystem::Instance(); + auto* memory = Libs::LibKernel::Memory::MemorySubsystem::Instance(); + auto* network = Libs::Network::NetworkSubsystem::Instance(); + auto* profiler = Profiler::ProfilerSubsystem::Instance(); + auto* pthread = Libs::LibKernel::PthreadSubsystem::Instance(); + auto* scripts = Scripts::ScriptsSubsystem::Instance(); + auto* timer = Loader::Timer::TimerSubsystem::Instance(); slist->Add(config, {core, scripts}); slist->InitAll(true); Config::Load(cfg); - slist->Add(log, {core, config}); - slist->Add(pthread, {core, log, timer}); - slist->Add(timer, {core, log}); - slist->Add(memory, {core, log}); + slist->Add(audio, {core, log, pthread, memory}); slist->Add(controller, {core, log, config}); slist->Add(file_system, {core, log, pthread}); slist->Add(graphics, {core, log, pthread, memory, config, profiler, controller}); + slist->Add(log, {core, config}); + slist->Add(memory, {core, log}); + slist->Add(network, {core, log, pthread}); slist->Add(profiler, {core, config}); + slist->Add(pthread, {core, log, timer}); + slist->Add(timer, {core, log}); slist->InitAll(true); } @@ -160,6 +166,22 @@ KYTY_SCRIPT_FUNC(kyty_load_elf_func) return 0; } +KYTY_SCRIPT_FUNC(kyty_save_main_elf_func) +{ + if (Scripts::ArgGetVarCount() != 1) + { + EXIT("invalid args\n"); + } + + Scripts::ScriptVar elf = Scripts::ArgGetVar(0); + + auto* rt = Core::Singleton::Instance(); + + rt->SaveMainProgram(Libs::LibKernel::FileSystem::GetRealFilename(elf.ToString())); + + return 0; +} + KYTY_SCRIPT_FUNC(kyty_load_symbols_func) { auto count = Scripts::ArgGetVarCount(); @@ -342,6 +364,7 @@ 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_save_main_elf", LuaFunc::kyty_save_main_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); Scripts::RegisterFunc("kyty_execute", LuaFunc::kyty_execute_func, LuaFunc::kyty_help); diff --git a/source/emulator/src/Libs/LibAudio.cpp b/source/emulator/src/Libs/LibAudio.cpp new file mode 100644 index 0000000..2dcbaa6 --- /dev/null +++ b/source/emulator/src/Libs/LibAudio.cpp @@ -0,0 +1,30 @@ +#include "Emulator/Audio.h" +#include "Emulator/Common.h" +#include "Emulator/Libs/Libs.h" +#include "Emulator/SymbolDatabase.h" + +#ifdef KYTY_EMU_ENABLED + +namespace Kyty::Libs { + +namespace LibVoiceQoS { + +LIB_VERSION("VoiceQoS", 1, "VoiceQoS", 0, 0); + +namespace VoiceQoS = Audio::VoiceQoS; + +LIB_DEFINE(InitAudio_1_VoiceQoS) +{ + LIB_FUNC("U8IfNl6-Css", VoiceQoS::VoiceQoSInit); +} + +} // namespace LibVoiceQoS + +LIB_DEFINE(InitAudio_1) +{ + LibVoiceQoS::InitAudio_1_VoiceQoS(s); +} + +} // namespace Kyty::Libs + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Libs/LibDialog.cpp b/source/emulator/src/Libs/LibDialog.cpp new file mode 100644 index 0000000..b9d65bd --- /dev/null +++ b/source/emulator/src/Libs/LibDialog.cpp @@ -0,0 +1,30 @@ +#include "Emulator/Common.h" +#include "Emulator/Dialog.h" +#include "Emulator/Libs/Libs.h" +#include "Emulator/SymbolDatabase.h" + +#ifdef KYTY_EMU_ENABLED + +namespace Kyty::Libs { + +namespace LibCommonDialog { + +LIB_VERSION("CommonDialog", 1, "CommonDialog", 1, 1); + +namespace CommonDialog = Dialog::CommonDialog; + +LIB_DEFINE(InitDialog_1_CommonDialog) +{ + LIB_FUNC("uoUpLGNkygk", CommonDialog::CommonDialogInitialize); +} + +} // namespace LibCommonDialog + +LIB_DEFINE(InitDialog_1) +{ + LibCommonDialog::InitDialog_1_CommonDialog(s); +} + +} // namespace Kyty::Libs + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Libs/LibKernel.cpp b/source/emulator/src/Libs/LibKernel.cpp index a9b058d..c1938d1 100644 --- a/source/emulator/src/Libs/LibKernel.cpp +++ b/source/emulator/src/Libs/LibKernel.cpp @@ -122,6 +122,17 @@ static KYTY_SYSV_ABI void stack_chk_fail() EXIT("stack fail!!!"); } +static KYTY_SYSV_ABI int sigprocmask(int /*how*/, const void* /*set*/, void* /*oset*/) +{ + // PRINT_NAME(); + + // printf("\t how = %d\n", how); + // printf("\t set = %016" PRIx64 "\n", reinterpret_cast(set)); + // printf("\t oset = %016" PRIx64 "\n", reinterpret_cast(oset)); + + return 0; +} + static KYTY_SYSV_ABI KernelModule KernelLoadStartModule(const char* module_file_name, size_t args, const void* argp, uint32_t flags, const KernelLoadModuleOpt* opt, int* res) { @@ -511,6 +522,9 @@ LIB_DEFINE(InitLibKernel_1_Pthread) LIB_FUNC("8+s5BzZjxSg", LibKernel::PthreadAttrGetaffinity); LIB_FUNC("nsYoNRywwNg", LibKernel::PthreadAttrInit); LIB_FUNC("JaRMy+QcpeU", LibKernel::PthreadAttrGetdetachstate); + LIB_FUNC("Ru36fiTtJzA", LibKernel::PthreadAttrGetstackaddr); + LIB_FUNC("-fA+7ZlGDQs", LibKernel::PthreadAttrGetstacksize); + LIB_FUNC("txHtngJ+eyc", LibKernel::PthreadAttrGetguardsize); LIB_FUNC("UTXzJbWhhTE", LibKernel::PthreadAttrSetstacksize); LIB_FUNC("-Wreprtu0Qs", LibKernel::PthreadAttrSetdetachstate); LIB_FUNC("eXbUSpEaTsA", LibKernel::PthreadAttrSetinheritsched); @@ -573,6 +587,7 @@ LIB_DEFINE(InitLibKernel_1) LIB_FUNC("Xjoosiw+XPI", LibKernel::KernelUuidCreate); LIB_FUNC("WslcK1FQcGI", LibKernel::KernelIsNeoMode); LIB_FUNC("9BcDykPmo1I", LibKernel::get_error_addr); + LIB_FUNC("6xVpy0Fdq+I", LibKernel::sigprocmask); LIB_FUNC("1jfXLRVzisc", LibKernel::KernelUsleep); LIB_FUNC("rNhWz+lvOMU", LibKernel::KernelSetThreadDtors); diff --git a/source/emulator/src/Libs/LibNet.cpp b/source/emulator/src/Libs/LibNet.cpp new file mode 100644 index 0000000..db10ac9 --- /dev/null +++ b/source/emulator/src/Libs/LibNet.cpp @@ -0,0 +1,179 @@ +#include "Kyty/Core/Common.h" + +#include "Emulator/Common.h" +#include "Emulator/Libs/Libs.h" +#include "Emulator/Network.h" +#include "Emulator/SymbolDatabase.h" + +#ifdef KYTY_EMU_ENABLED + +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define NET_CALL(func) \ + [&]() \ + { \ + auto result = func; \ + if (result < 0) \ + { \ + *GetNetErrorAddr() = result; \ + } \ + return result; \ + }() + +namespace Kyty::Libs { + +namespace Network::Net { +struct NetEtherAddr; +} // namespace Network::Net + +namespace LibNet { + +LIB_VERSION("Net", 1, "Net", 1, 1); + +static thread_local int g_net_errno = 0; + +namespace Net = Network::Net; + +KYTY_SYSV_ABI int* GetNetErrorAddr() +{ + return &g_net_errno; +} + +static int KYTY_SYSV_ABI NetInit() +{ + return NET_CALL(Net::NetInit()); +} + +int KYTY_SYSV_ABI NetPoolCreate(const char* name, int size, int flags) +{ + return NET_CALL(Net::NetPoolCreate(name, size, flags)); +} + +int KYTY_SYSV_ABI NetInetPton(int af, const char* src, void* dst) +{ + return NET_CALL(Net::NetInetPton(af, src, dst)); +} + +int KYTY_SYSV_ABI NetEtherNtostr(const Net::NetEtherAddr* n, char* str, size_t len) +{ + return NET_CALL(Net::NetEtherNtostr(n, str, len)); +} + +int KYTY_SYSV_ABI NetGetMacAddress(Net::NetEtherAddr* addr, int flags) +{ + return NET_CALL(Net::NetGetMacAddress(addr, flags)); +} + +LIB_DEFINE(InitNet_1_Net) +{ + LIB_FUNC("Nlev7Lg8k3A", LibNet::NetInit); + LIB_FUNC("dgJBaeJnGpo", LibNet::NetPoolCreate); + LIB_FUNC("8Kcp5d-q1Uo", LibNet::NetInetPton); + LIB_FUNC("v6M4txecCuo", LibNet::NetEtherNtostr); + LIB_FUNC("6Oc0bLsIYe0", LibNet::NetGetMacAddress); +} + +} // namespace LibNet + +namespace LibSsl { + +LIB_VERSION("Ssl", 1, "Ssl", 1, 1); + +namespace Ssl = Network::Ssl; + +LIB_DEFINE(InitNet_1_Ssl) +{ + LIB_FUNC("hdpVEUDFW3s", Ssl::SslInit); +} + +} // namespace LibSsl + +namespace LibHttp { + +LIB_VERSION("Http", 1, "Http", 1, 1); + +namespace Http = Network::Http; + +LIB_DEFINE(InitNet_1_Http) +{ + LIB_FUNC("A9cVMUtEp4Y", Http::HttpInit); + LIB_FUNC("0gYjPTR-6cY", Http::HttpCreateTemplate); +} + +} // namespace LibHttp + +namespace LibNetCtl { + +LIB_VERSION("NetCtl", 1, "NetCtl", 1, 1); + +namespace NetCtl = Network::NetCtl; + +LIB_DEFINE(InitNet_1_NetCtl) +{ + LIB_FUNC("gky0+oaNM4k", NetCtl::NetCtlInit); + LIB_FUNC("JO4yuTuMoKI", NetCtl::NetCtlGetNatInfo); + LIB_FUNC("iQw3iQPhvUQ", NetCtl::NetCtlCheckCallback); + LIB_FUNC("uBPlr0lbuiI", NetCtl::NetCtlGetState); + LIB_FUNC("UJ+Z7Q+4ck0", NetCtl::NetCtlRegisterCallback); + LIB_FUNC("obuxdTiwkF8", NetCtl::NetCtlGetInfo); +} + +} // namespace LibNetCtl + +namespace LibNpManager { + +LIB_VERSION("NpManager", 1, "NpManager", 1, 1); + +namespace NpManager = Network::NpManager; + +LIB_DEFINE(InitNet_1_NpManager) +{ + LIB_FUNC("3Zl8BePTh9Y", NpManager::NpCheckCallback); + LIB_FUNC("Ec63y59l9tw", NpManager::NpSetNpTitleId); + LIB_FUNC("A2CQ3kgSopQ", NpManager::NpSetContentRestriction); + LIB_FUNC("VfRSmPmj8Q8", NpManager::NpRegisterStateCallback); + LIB_FUNC("uFJpaKNBAj4", NpManager::NpRegisterGamePresenceCallback); + LIB_FUNC("GImICnh+boA", NpManager::NpRegisterPlusEventCallback); +} + +} // namespace LibNpManager + +namespace LibNpTrophy { + +LIB_VERSION("NpTrophy", 1, "NpTrophy", 1, 1); + +namespace NpTrophy = Network::NpTrophy; + +LIB_DEFINE(InitNet_1_NpTrophy) +{ + LIB_FUNC("q7U6tEAQf7c", NpTrophy::NpTrophyCreateHandle); +} + +} // namespace LibNpTrophy + +namespace LibNpWebApi { + +LIB_VERSION("NpWebApi", 1, "NpWebApi", 1, 1); + +namespace NpWebApi = Network::NpWebApi; + +LIB_DEFINE(InitNet_1_NpWebApi) +{ + LIB_FUNC("G3AnLNdRBjE", NpWebApi::NpWebApiInitialize); +} + +} // namespace LibNpWebApi + +LIB_DEFINE(InitNet_1) +{ + LibNet::InitNet_1_Net(s); + LibSsl::InitNet_1_Ssl(s); + LibHttp::InitNet_1_Http(s); + LibNetCtl::InitNet_1_NetCtl(s); + LibNpManager::InitNet_1_NpManager(s); + LibNpTrophy::InitNet_1_NpTrophy(s); + LibNpWebApi::InitNet_1_NpWebApi(s); +} + +} // namespace Kyty::Libs + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Libs/LibPlayGo.cpp b/source/emulator/src/Libs/LibPlayGo.cpp new file mode 100644 index 0000000..115da48 --- /dev/null +++ b/source/emulator/src/Libs/LibPlayGo.cpp @@ -0,0 +1,88 @@ +#include "Kyty/Core/Common.h" +#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("PlayGo", 1, "PlayGo", 1, 0); + +namespace PlayGo { + +struct PlayGoInitParams +{ + const void* buf_addr; + uint32_t buf_size; + uint32_t reserved; +}; + +int KYTY_SYSV_ABI PlayGoInitialize(const PlayGoInitParams* init) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(init == nullptr); + + printf("\t buf_addr = %016" PRIx64 "\n", reinterpret_cast(init->buf_addr)); + printf("\t buf_size = %" PRIu32 "\n", init->buf_size); + printf("\t reserved = %" PRId32 "\n", init->reserved); + + return OK; +} + +int KYTY_SYSV_ABI PlayGoOpen(int* out_handle, const void* param) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(out_handle == nullptr); + EXIT_NOT_IMPLEMENTED(param != nullptr); + + *out_handle = 1; + + return OK; +} + +int KYTY_SYSV_ABI PlayGoGetLocus(int handle, const uint16_t* chunk_ids, uint32_t number_of_entries, int8_t* out_loci) +{ + PRINT_NAME(); + + printf("\t handle = %d\n", handle); + + EXIT_NOT_IMPLEMENTED(handle != 1); + EXIT_NOT_IMPLEMENTED(chunk_ids == nullptr); + EXIT_NOT_IMPLEMENTED(out_loci == nullptr); + EXIT_NOT_IMPLEMENTED(number_of_entries != 1); + + for (uint32_t i = 0; i < number_of_entries; i++) + { + printf("\t chunk_ids[%u] = %" PRIu16 "\n", i, chunk_ids[i]); + + if (chunk_ids[i] == 0) + { + out_loci[i] = 3; + } else + { + return PLAYGO_ERROR_BAD_CHUNK_ID; + } + } + + return OK; +} + +} // namespace PlayGo + +LIB_DEFINE(InitPlayGo_1) +{ + LIB_FUNC("ts6GlZOKRrE", PlayGo::PlayGoInitialize); + LIB_FUNC("M1Gma1ocrGE", PlayGo::PlayGoOpen); + LIB_FUNC("uWIYLFkkwqk", PlayGo::PlayGoGetLocus); +} + +} // namespace Kyty::Libs + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Libs/LibSaveData.cpp b/source/emulator/src/Libs/LibSaveData.cpp new file mode 100644 index 0000000..0454297 --- /dev/null +++ b/source/emulator/src/Libs/LibSaveData.cpp @@ -0,0 +1,54 @@ +#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("SaveData", 1, "SaveData", 1, 1); + +namespace SaveData { + +int KYTY_SYSV_ABI SaveDataInitialize(const void* /*init*/) +{ + PRINT_NAME(); + + // EXIT_NOT_IMPLEMENTED(init != nullptr); + + return OK; +} + +int KYTY_SYSV_ABI SaveDataInitialize2(const void* /*init*/) +{ + PRINT_NAME(); + + // EXIT_NOT_IMPLEMENTED(init != nullptr); + + return OK; +} + +int KYTY_SYSV_ABI SaveDataInitialize3(const void* /*init*/) +{ + PRINT_NAME(); + + // EXIT_NOT_IMPLEMENTED(init != nullptr); + + return OK; +} + +} // namespace SaveData + +LIB_DEFINE(InitSaveData_1) +{ + LIB_FUNC("ZkZhskCPXFw", SaveData::SaveDataInitialize); + LIB_FUNC("l1NmDeDpNGU", SaveData::SaveDataInitialize2); + LIB_FUNC("TywrFKCoLGY", SaveData::SaveDataInitialize3); +} + +} // namespace Kyty::Libs + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Libs/LibSystemService.cpp b/source/emulator/src/Libs/LibSystemService.cpp index dce94c8..5fe88e5 100644 --- a/source/emulator/src/Libs/LibSystemService.cpp +++ b/source/emulator/src/Libs/LibSystemService.cpp @@ -1,3 +1,4 @@ +#include "Kyty/Core/Common.h" #include "Kyty/Core/DbgAssert.h" #include "Kyty/Core/String.h" @@ -79,6 +80,16 @@ namespace SystemService { [[maybe_unused]] constexpr int PARAM_ENTER_BUTTON_ASSIGN_CIRCLE = 0; [[maybe_unused]] constexpr int PARAM_ENTER_BUTTON_ASSIGN_CROSS = 1; +struct SystemServiceStatus +{ + int32_t event_num = 0; + bool is_system_ui_overlaid = false; + bool is_in_background_execution = false; + bool is_cpu_mode_7cpu_normal = true; + bool is_game_live_streaming_on_air = false; + bool is_out_of_vr_play_area = false; +}; + static int KYTY_SYSV_ABI SystemServiceHideSplashScreen() { PRINT_NAME(); @@ -116,12 +127,27 @@ static int KYTY_SYSV_ABI SystemServiceParamGetInt(int param_id, int* value) return OK; } +static int KYTY_SYSV_ABI SystemServiceGetStatus(SystemServiceStatus* status) +{ + PRINT_NAME(); + + if (status == nullptr) + { + return SYSTEM_SERVICE_ERROR_PARAMETER; + } + + *status = SystemServiceStatus(); + + return OK; +} + } // namespace SystemService LIB_DEFINE(InitSystemService_1) { LIB_FUNC("Vo5V8KAwCmk", SystemService::SystemServiceHideSplashScreen); LIB_FUNC("fZo48un7LK4", SystemService::SystemServiceParamGetInt); + LIB_FUNC("rPo6tV8D9bM", SystemService::SystemServiceGetStatus); } } // namespace Kyty::Libs diff --git a/source/emulator/src/Libs/LibUserService.cpp b/source/emulator/src/Libs/LibUserService.cpp index d021339..8f38991 100644 --- a/source/emulator/src/Libs/LibUserService.cpp +++ b/source/emulator/src/Libs/LibUserService.cpp @@ -2,6 +2,7 @@ #include "Kyty/Core/String.h" #include "Emulator/Common.h" +#include "Emulator/Libs/Errno.h" #include "Emulator/Libs/Libs.h" #include "Emulator/SymbolDatabase.h" @@ -17,7 +18,7 @@ static KYTY_SYSV_ABI int UserServiceInitialize(const void* /*params*/) { PRINT_NAME(); - return 0; + return OK; } static KYTY_SYSV_ABI int UserServiceGetInitialUser(int* user_id) @@ -28,7 +29,16 @@ static KYTY_SYSV_ABI int UserServiceGetInitialUser(int* user_id) *user_id = 1; - return 0; + return OK; +} + +static KYTY_SYSV_ABI int UserServiceGetEvent(void* event) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(event == nullptr); + + return USER_SERVICE_ERROR_NO_EVENT; } } // namespace UserService @@ -37,6 +47,7 @@ LIB_DEFINE(InitUserService_1) { LIB_FUNC("j3YMu1MVNNo", UserService::UserServiceInitialize); LIB_FUNC("CdWp0oHWGr0", UserService::UserServiceGetInitialUser); + LIB_FUNC("yH17Q6NWtVg", UserService::UserServiceGetEvent); } } // namespace Kyty::Libs diff --git a/source/emulator/src/Libs/Libs.cpp b/source/emulator/src/Libs/Libs.cpp index cbcce9e..0a99d24 100644 --- a/source/emulator/src/Libs/Libs.cpp +++ b/source/emulator/src/Libs/Libs.cpp @@ -8,30 +8,40 @@ namespace LibcInternal { LIB_DEFINE(InitLibcInternal_1); } // namespace LibcInternal +LIB_DEFINE(InitAudio_1); +LIB_DEFINE(InitDebug_1); +LIB_DEFINE(InitDialog_1); +LIB_DEFINE(InitDiscMap_1); +LIB_DEFINE(InitGraphicsDriver_1); LIB_DEFINE(InitLibC_1); LIB_DEFINE(InitLibKernel_1); -LIB_DEFINE(InitVideoOut_1); +LIB_DEFINE(InitNet_1); +LIB_DEFINE(InitPad_1); +LIB_DEFINE(InitPlayGo_1); +LIB_DEFINE(InitSaveData_1); 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); +LIB_DEFINE(InitVideoOut_1); bool Init(const String& id, Loader::SymbolDatabase* s) { + LIB_CHECK(U"libAudio_1", InitAudio_1); LIB_CHECK(U"libc_1", InitLibC_1); LIB_CHECK(U"libc_internal_1", LibcInternal::InitLibcInternal_1); - LIB_CHECK(U"libkernel_1", InitLibKernel_1); - LIB_CHECK(U"libVideoOut_1", InitVideoOut_1); - LIB_CHECK(U"libSysmodule_1", InitSysmodule_1); - LIB_CHECK(U"libDiscMap_1", InitDiscMap_1); LIB_CHECK(U"libDebug_1", InitDebug_1); + LIB_CHECK(U"libDialog_1", InitDialog_1); + LIB_CHECK(U"libDiscMap_1", InitDiscMap_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"libkernel_1", InitLibKernel_1); + LIB_CHECK(U"libNet_1", InitNet_1); LIB_CHECK(U"libPad_1", InitPad_1); + LIB_CHECK(U"libPlayGo_1", InitPlayGo_1); + LIB_CHECK(U"libSaveData_1", InitSaveData_1); + LIB_CHECK(U"libSysmodule_1", InitSysmodule_1); + LIB_CHECK(U"libSystemService_1", InitSystemService_1); + LIB_CHECK(U"libUserService_1", InitUserService_1); + LIB_CHECK(U"libVideoOut_1", InitVideoOut_1); return false; } diff --git a/source/emulator/src/Log.cpp b/source/emulator/src/Log.cpp index 14a1440..989a28e 100644 --- a/source/emulator/src/Log.cpp +++ b/source/emulator/src/Log.cpp @@ -143,6 +143,13 @@ void SetDirection(Direction dir) g_dir = dir; } +Direction GetDirection() +{ + EXIT_IF(!Log::g_log_initialized); + + return g_dir; +} + void SetOutputFile(const String& file_name, Core::File::Encoding enc) { EXIT_IF(!Log::g_log_initialized); diff --git a/source/emulator/src/Network.cpp b/source/emulator/src/Network.cpp new file mode 100644 index 0000000..c5db239 --- /dev/null +++ b/source/emulator/src/Network.cpp @@ -0,0 +1,742 @@ +#include "Emulator/Network.h" + +#include "Kyty/Core/ByteBuffer.h" +#include "Kyty/Core/Common.h" +#include "Kyty/Core/DbgAssert.h" +#include "Kyty/Core/String.h" +#include "Kyty/Core/Threads.h" +#include "Kyty/Core/Vector.h" + +#include "Emulator/Libs/Errno.h" +#include "Emulator/Libs/Libs.h" + +#ifdef KYTY_EMU_ENABLED + +namespace Kyty::Libs::Network { + +class Network +{ +public: + Network() = default; + virtual ~Network() = default; + + KYTY_CLASS_NO_COPY(Network); + + int PoolCreate(const char* name, int size); + bool PoolDestroy(int memid); + + int SslInit(uint64_t pool_size); + bool SslTerm(int ssl_ctx_id); + + int HttpInit(int memid, int ssl_ctx_id, uint64_t pool_size); + bool HttpTerm(int http_ctx_id); + int HttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver, bool is_auto_proxy_conf); + bool HttpDeleteTemplate(int tmpl_id); + bool HttpValid(int http_ctx_id); + +private: + struct Pool + { + bool used = false; + String name; + int size = 0; + }; + + struct Ssl + { + bool used = false; + uint64_t size = 0; + }; + + struct Http + { + bool used = false; + uint64_t size = 0; + int memid = 0; + int ssl_ctx_id = 0; + }; + + struct HttpTemplate + { + bool used = false; + int http_ctx_id = 0; + String user_agent; + int http_ver = 0; + bool is_auto_proxy_conf = true; + }; + + static constexpr int POOLS_MAX = 32; + static constexpr int SSL_MAX = 32; + static constexpr int HTTP_MAX = 32; + + Core::Mutex m_mutex; + Pool m_pools[POOLS_MAX]; + Ssl m_ssl[SSL_MAX]; + Http m_http[HTTP_MAX]; + Vector m_templates; +}; + +static Network* g_net = nullptr; + +KYTY_SUBSYSTEM_INIT(Network) +{ + EXIT_IF(g_net != nullptr); + + g_net = new Network; +} + +KYTY_SUBSYSTEM_UNEXPECTED_SHUTDOWN(Network) {} + +KYTY_SUBSYSTEM_DESTROY(Network) {} + +int Network::PoolCreate(const char* name, int size) +{ + Core::LockGuard lock(m_mutex); + + for (int id = 0; id < POOLS_MAX; id++) + { + if (!m_pools[id].used) + { + m_pools[id].used = true; + m_pools[id].size = size; + m_pools[id].name = String::FromUtf8(name); + + return id; + } + } + + return -1; +} + +bool Network::PoolDestroy(int memid) +{ + Core::LockGuard lock(m_mutex); + + if (memid >= 0 && memid < POOLS_MAX && m_pools[memid].used) + { + m_pools[memid].used = false; + + return true; + } + + return false; +} + +int Network::SslInit(uint64_t pool_size) +{ + Core::LockGuard lock(m_mutex); + + for (int id = 0; id < SSL_MAX; id++) + { + if (!m_ssl[id].used) + { + m_ssl[id].used = true; + m_ssl[id].size = pool_size; + + return id; + } + } + + return -1; +} + +bool Network::SslTerm(int ssl_ctx_id) +{ + Core::LockGuard lock(m_mutex); + + if (ssl_ctx_id >= 0 && ssl_ctx_id < SSL_MAX && m_ssl[ssl_ctx_id].used) + { + m_ssl[ssl_ctx_id].used = false; + + return true; + } + + return false; +} + +int Network::HttpInit(int memid, int ssl_ctx_id, uint64_t pool_size) +{ + Core::LockGuard lock(m_mutex); + + if (ssl_ctx_id >= 0 && ssl_ctx_id < SSL_MAX && m_ssl[ssl_ctx_id].used && memid >= 0 && memid < POOLS_MAX && m_pools[memid].used) + { + for (int id = 0; id < HTTP_MAX; id++) + { + if (!m_http[id].used) + { + m_http[id].used = true; + m_http[id].size = pool_size; + m_http[id].ssl_ctx_id = ssl_ctx_id; + m_http[id].memid = memid; + + return id; + } + } + } + + return -1; +} + +bool Network::HttpValid(int http_ctx_id) +{ + Core::LockGuard lock(m_mutex); + + return (http_ctx_id >= 0 && http_ctx_id < HTTP_MAX && m_http[http_ctx_id].used); +} + +bool Network::HttpTerm(int http_ctx_id) +{ + Core::LockGuard lock(m_mutex); + + if (HttpValid(http_ctx_id)) + { + m_http[http_ctx_id].used = false; + + return true; + } + + return false; +} + +int Network::HttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver, bool is_auto_proxy_conf) +{ + Core::LockGuard lock(m_mutex); + + if (http_ctx_id >= 0 && http_ctx_id < HTTP_MAX && m_http[http_ctx_id].used) + { + HttpTemplate tn {}; + tn.used = true; + tn.http_ver = http_ver; + tn.user_agent = String::FromUtf8(user_agent); + tn.is_auto_proxy_conf = is_auto_proxy_conf; + tn.http_ctx_id = http_ctx_id; + + int index = 0; + for (auto& t: m_templates) + { + if (!t.used) + { + t = tn; + return index; + } + index++; + } + + m_templates.Add(tn); + + return index; + } + + return -1; +} + +bool Network::HttpDeleteTemplate(int tmpl_id) +{ + Core::LockGuard lock(m_mutex); + + if (m_templates.IndexValid(tmpl_id) && m_templates.At(tmpl_id).used) + { + m_templates[tmpl_id].used = false; + + return true; + } + + return false; +} + +namespace Net { + +LIB_NAME("Net", "Net"); + +struct NetEtherAddr +{ + uint8_t data[6] = {0}; +}; + +int KYTY_SYSV_ABI NetInit() +{ + PRINT_NAME(); + + return OK; +} + +int KYTY_SYSV_ABI NetTerm() +{ + PRINT_NAME(); + + return OK; +} + +int KYTY_SYSV_ABI NetPoolCreate(const char* name, int size, int flags) +{ + PRINT_NAME(); + + printf("\t name = %s\n", name); + printf("\t size = %d\n", size); + printf("\t flags = %d\n", flags); + + EXIT_IF(g_net == nullptr); + + EXIT_NOT_IMPLEMENTED(flags != 0); + EXIT_NOT_IMPLEMENTED(size == 0); + + int id = g_net->PoolCreate(name, size); + + if (id < 0) + { + return NET_ERROR_ENFILE; + } + + return id; +} + +int KYTY_SYSV_ABI NetPoolDestroy(int memid) +{ + PRINT_NAME(); + + EXIT_IF(g_net == nullptr); + + if (!g_net->PoolDestroy(memid)) + { + return NET_ERROR_EBADF; + } + + return OK; +} + +int KYTY_SYSV_ABI NetInetPton(int af, const char* src, void* dst) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(af != 2); + EXIT_NOT_IMPLEMENTED(src == nullptr); + EXIT_NOT_IMPLEMENTED(dst == nullptr); + EXIT_NOT_IMPLEMENTED(strcmp(src, "127.0.0.1") != 0); + + printf("\t src = %.16s\n", src); + + *static_cast(dst) = 0x7f000001; + + return OK; +} + +int KYTY_SYSV_ABI NetEtherNtostr(const NetEtherAddr* n, char* str, size_t len) +{ + PRINT_NAME(); + + NetEtherAddr zero {}; + + EXIT_NOT_IMPLEMENTED(len != 18); + EXIT_NOT_IMPLEMENTED(n == nullptr); + EXIT_NOT_IMPLEMENTED(str == nullptr); + EXIT_NOT_IMPLEMENTED(memcmp(n->data, zero.data, sizeof(zero.data)) != 0); + + strcpy(str, "00:00:00:00:00:00"); // NOLINT + + return OK; +} + +int KYTY_SYSV_ABI NetGetMacAddress(NetEtherAddr* addr, int flags) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(addr == nullptr); + EXIT_NOT_IMPLEMENTED(flags != 0); + + memset(addr->data, 0, sizeof(addr->data)); + + return OK; +} + +} // namespace Net + +namespace Ssl { + +LIB_NAME("Ssl", "Ssl"); + +int KYTY_SYSV_ABI SslInit(uint64_t pool_size) +{ + PRINT_NAME(); + + printf("\t size = %" PRIu64 "\n", pool_size); + + EXIT_IF(g_net == nullptr); + + EXIT_NOT_IMPLEMENTED(pool_size == 0); + + int id = g_net->SslInit(pool_size); + + if (id < 0) + { + return SSL_ERROR_OUT_OF_SIZE; + } + + return id + 1; +} + +int KYTY_SYSV_ABI SslTerm(int ssl_ctx_id) +{ + PRINT_NAME(); + + EXIT_IF(g_net == nullptr); + + if (!g_net->SslTerm(ssl_ctx_id - 1)) + { + return SSL_ERROR_INVALID_ID; + } + + return OK; +} + +} // namespace Ssl + +namespace Http { + +LIB_NAME("Http", "Http"); + +int KYTY_SYSV_ABI HttpInit(int memid, int ssl_ctx_id, uint64_t pool_size) +{ + PRINT_NAME(); + + printf("\t memid = %d\n", memid); + printf("\t ssl_ctx_id = %d\n", ssl_ctx_id); + printf("\t size = %" PRIu64 "\n", pool_size); + + EXIT_IF(g_net == nullptr); + + EXIT_NOT_IMPLEMENTED(pool_size == 0); + + int id = g_net->HttpInit(memid, ssl_ctx_id - 1, pool_size); + + if (id < 0) + { + return HTTP_ERROR_OUT_OF_MEMORY; + } + + return id + 1; +} + +int KYTY_SYSV_ABI HttpTerm(int http_ctx_id) +{ + PRINT_NAME(); + + EXIT_IF(g_net == nullptr); + + if (!g_net->HttpTerm(http_ctx_id - 1)) + { + return HTTP_ERROR_INVALID_ID; + } + + return OK; +} + +int KYTY_SYSV_ABI HttpCreateTemplate(int http_ctx_id, const char* user_agent, int http_ver, int is_auto_proxy_conf) +{ + PRINT_NAME(); + + printf("\t http_ctx_id = %d\n", http_ctx_id); + printf("\t user_agent = %s\n", user_agent); + printf("\t http_ver = %d\n", http_ver); + printf("\t is_auto_proxy_conf = %d\n", is_auto_proxy_conf); + + EXIT_IF(g_net == nullptr); + + int id = g_net->HttpCreateTemplate(http_ctx_id, user_agent, http_ver, is_auto_proxy_conf != 0); + + if (id < 0) + { + return HTTP_ERROR_OUT_OF_MEMORY; + } + + return id + 1; +} + +int KYTY_SYSV_ABI HttpDeleteTemplate(int tmpl_id) +{ + PRINT_NAME(); + + EXIT_IF(g_net == nullptr); + + if (!g_net->HttpDeleteTemplate(tmpl_id - 1)) + { + return HTTP_ERROR_INVALID_ID; + } + + return OK; +} + +} // namespace Http + +namespace NetCtl { + +LIB_NAME("NetCtl", "NetCtl"); + +struct NetInAddr +{ + uint32_t s_addr = 0; +}; + +struct NetEtherAddr +{ + uint8_t data[6]; +}; + +struct NetCtlNatInfo +{ + unsigned int size = sizeof(NetCtlNatInfo); + int stunStatus = 0; + int natType = 0; + NetInAddr mappedAddr; +}; + +union NetCtlInfo +{ + uint32_t device; + NetEtherAddr ether_addr; + uint32_t mtu; + uint32_t link; + NetEtherAddr bssid; + char ssid[32 + 1]; + uint32_t wifi_security; + uint8_t rssi_dbm; + uint8_t rssi_percentage; + uint8_t channel; + uint32_t ip_config; + char dhcp_hostname[255 + 1]; + char pppoe_auth_name[127 + 1]; + char ip_address[16]; + char netmask[16]; + char default_route[16]; + char primary_dns[16]; + char secondary_dns[16]; + uint32_t http_proxy_config; + char http_proxy_server[255 + 1]; + uint16_t http_proxy_port; +}; + +int KYTY_SYSV_ABI NetCtlInit() +{ + PRINT_NAME(); + + return OK; +} + +void KYTY_SYSV_ABI NetCtlTerm() +{ + PRINT_NAME(); +} + +int KYTY_SYSV_ABI NetCtlGetNatInfo(NetCtlNatInfo* nat_info) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(nat_info == nullptr); + EXIT_NOT_IMPLEMENTED(nat_info->size != sizeof(NetCtlNatInfo)); + + nat_info->stunStatus = 1; + nat_info->natType = 3; + nat_info->mappedAddr.s_addr = 0x7f000001; + + return OK; +} + +int KYTY_SYSV_ABI NetCtlCheckCallback() +{ + PRINT_NAME(); + + return OK; +} + +int KYTY_SYSV_ABI NetCtlGetState(int* state) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(state == nullptr); + + *state = 0; // Disconnected + + return OK; +} + +int KYTY_SYSV_ABI NetCtlRegisterCallback(NetCtlCallback func, void* /*arg*/, int* cid) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(func == nullptr); + EXIT_NOT_IMPLEMENTED(cid == nullptr); + + *cid = 1; + + return OK; +} + +int KYTY_SYSV_ABI NetCtlGetInfo(int code, NetCtlInfo* info) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(info == nullptr); + + printf("\t code = %d\n", code); + + switch (code) + { + case 2: memset(info->ether_addr.data, 0, sizeof(info->ether_addr.data)); break; + case 11: info->ip_config = 0; break; + case 14: strcpy(info->ip_address, "127.0.0.1"); break; + default: EXIT("unknown code: %d\n", code); + } + + return OK; +} + +} // namespace NetCtl + +namespace NpManager { + +LIB_NAME("NpManager", "NpManager"); + +struct NpTitleId +{ + char id[12 + 1]; + uint8_t padding[3]; +}; + +struct NpTitleSecret +{ + uint8_t data[128]; +}; + +struct NpCountryCode +{ + char data[2]; + char term; + char padding[1]; +}; + +struct NpAgeRestriction +{ + NpCountryCode country_code; + int8_t age; + uint8_t padding[3]; +}; + +struct NpContentRestriction +{ + size_t size; + int8_t default_age_restriction; + char padding[3]; + int32_t age_restriction_count; + const NpAgeRestriction* age_restriction; +}; + +int KYTY_SYSV_ABI NpCheckCallback() +{ + PRINT_NAME(); + + return OK; +} + +int KYTY_SYSV_ABI NpSetNpTitleId(const NpTitleId* title_id, const NpTitleSecret* title_secret) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(title_id == nullptr); + EXIT_NOT_IMPLEMENTED(title_secret == nullptr); + + printf("\t title_id = %.12s\n", title_id->id); + printf("\t title_secret = %s\n", String::HexFromBin(Core::ByteBuffer(title_secret->data, 128)).C_Str()); + + return OK; +} + +int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restriction) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(restriction == nullptr); + EXIT_NOT_IMPLEMENTED(restriction->size != sizeof(NpContentRestriction)); + + printf("\t default_age_restriction = %" PRIi8 "\n", restriction->default_age_restriction); + printf("\t age_restriction_count = %" PRIi32 "\n", restriction->age_restriction_count); + + for (int i = 0; i < restriction->age_restriction_count; i++) + { + printf("\t age_restriction[%d].age = %" PRIi8 "\n", i, restriction->age_restriction[i].age); + printf("\t age_restriction[%d].country_code.data = %.2s\n", i, restriction->age_restriction[i].country_code.data); + } + + return OK; +} + +int KYTY_SYSV_ABI NpRegisterStateCallback(void* /*callback*/, void* /*userdata*/) +{ + PRINT_NAME(); + + return OK; +} + +void KYTY_SYSV_ABI NpRegisterGamePresenceCallback(void* /*callback*/, void* /*userdata*/) +{ + PRINT_NAME(); +} + +int KYTY_SYSV_ABI NpRegisterPlusEventCallback(void* /*callback*/, void* /*userdata*/) +{ + PRINT_NAME(); + + return OK; +} + +} // namespace NpManager + +namespace NpTrophy { + +LIB_NAME("NpTrophy", "NpTrophy"); + +int KYTY_SYSV_ABI NpTrophyCreateHandle(int* handle) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(handle == nullptr); + + *handle = 1; + + return OK; +} + +} // namespace NpTrophy + +namespace NpWebApi { + +LIB_NAME("NpWebApi", "NpWebApi"); + +int KYTY_SYSV_ABI NpWebApiInitialize(int http_ctx_id, size_t pool_size) +{ + PRINT_NAME(); + + EXIT_IF(g_net == nullptr); + + printf("\t http_ctx_id = %d\n", http_ctx_id); + printf("\t pool_size = %" PRIu64 "\n", pool_size); + + EXIT_NOT_IMPLEMENTED(!g_net->HttpValid(http_ctx_id - 1)); + + static int id = 0; + + return ++id; +} + +int KYTY_SYSV_ABI NpWebApiTerminate(int lib_ctx_id) +{ + PRINT_NAME(); + + printf("\t lib_ctx_id = %d\n", lib_ctx_id); + + return OK; +} + +} // namespace NpWebApi + +} // namespace Kyty::Libs::Network + +#endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/RuntimeLinker.cpp b/source/emulator/src/RuntimeLinker.cpp index 553564b..a229d25 100644 --- a/source/emulator/src/RuntimeLinker.cpp +++ b/source/emulator/src/RuntimeLinker.cpp @@ -683,6 +683,24 @@ Program* RuntimeLinker::LoadProgram(const String& elf_name) return program; } +void RuntimeLinker::SaveMainProgram(const String& elf_name) +{ + EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); + + Core::LockGuard lock(m_mutex); + + for (const auto* p: m_programs) + { + EXIT_IF(p->elf == nullptr); + + if (!p->elf->IsShared()) + { + p->elf->Save(elf_name); + break; + } + } +} + void RuntimeLinker::Clear() { // EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread()); diff --git a/source/launcher/include/Configuration.h b/source/launcher/include/Configuration.h index 78a5ae4..d025286 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", "libSystemService_1", "libPad_1" \ + "libUserService_1", "libSystemService_1", "libPad_1", "libNet_1", "libDialog_1", "libAudio_1", "libPlayGo_1", "libSaveData_1" \ } template