mirror of https://github.com/InoriRus/Kyty.git
more APIs
This commit is contained in:
parent
877560b7f6
commit
16baf5cc18
|
@ -1,4 +1,4 @@
|
|||
version: 0.1.4.build-{build}
|
||||
version: 0.1.5.build-{build}
|
||||
image: Visual Studio 2019
|
||||
environment:
|
||||
matrix:
|
||||
|
|
|
@ -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.1.4)
|
||||
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.5)
|
||||
|
||||
include(src_script.cmake)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ KYTY_SUBSYSTEM_DEFINE(Audio);
|
|||
namespace AudioOut {
|
||||
|
||||
struct AudioOutOutputParam;
|
||||
struct AudioOutPortState;
|
||||
|
||||
int KYTY_SYSV_ABI AudioOutInit();
|
||||
int KYTY_SYSV_ABI AudioOutOpen(int user_id, int type, int index, uint32_t len, uint32_t freq, uint32_t param);
|
||||
|
@ -22,6 +23,7 @@ int KYTY_SYSV_ABI AudioOutSetVolume(int handle, uint32_t flag, int* vol);
|
|||
int KYTY_SYSV_ABI AudioOutOutputs(AudioOutOutputParam* param, uint32_t num);
|
||||
int KYTY_SYSV_ABI AudioOutOutput(int handle, const void* ptr);
|
||||
int KYTY_SYSV_ABI AudioOutClose(int handle);
|
||||
int KYTY_SYSV_ABI AudioOutGetPortState(int handle, AudioOutPortState* state);
|
||||
|
||||
} // namespace AudioOut
|
||||
|
||||
|
@ -64,6 +66,43 @@ int KYTY_SYSV_ABI AvPlayerClose(AvPlayerInternal* h);
|
|||
|
||||
} // namespace AvPlayer
|
||||
|
||||
namespace Audio3d {
|
||||
|
||||
struct Audio3dOpenParameters;
|
||||
|
||||
int KYTY_SYSV_ABI Audio3dInitialize(int64_t reserved);
|
||||
void KYTY_SYSV_ABI Audio3dGetDefaultOpenParameters(Audio3dOpenParameters* p);
|
||||
int KYTY_SYSV_ABI Audio3dPortOpen(int user_id, const Audio3dOpenParameters* parameters, uint32_t* id);
|
||||
int KYTY_SYSV_ABI Audio3dPortSetAttribute(uint32_t port_id, uint32_t attribute_id, const void* attribute, size_t attribute_size);
|
||||
int KYTY_SYSV_ABI Audio3dPortGetQueueLevel(uint32_t port_id, uint32_t* queue_level, uint32_t* queue_available);
|
||||
int KYTY_SYSV_ABI Audio3dPortAdvance(uint32_t port_id);
|
||||
int KYTY_SYSV_ABI Audio3dPortPush(uint32_t port_id, uint32_t blocking);
|
||||
|
||||
} // namespace Audio3d
|
||||
|
||||
namespace Ngs2 {
|
||||
|
||||
struct Ngs2SystemOption;
|
||||
struct Ngs2RackOption;
|
||||
struct Ngs2BufferAllocator;
|
||||
struct Ngs2VoiceParamHeader;
|
||||
struct Ngs2RenderBufferInfo;
|
||||
struct Ngs2ContextBufferInfo;
|
||||
struct Ngs2VoiceState;
|
||||
|
||||
int KYTY_SYSV_ABI Ngs2RackQueryBufferSize(uint32_t rack_id, const Ngs2RackOption* option, Ngs2ContextBufferInfo* buffer_info);
|
||||
int KYTY_SYSV_ABI Ngs2RackCreate(uintptr_t system_handle, uint32_t rack_id, const Ngs2RackOption* option,
|
||||
const Ngs2ContextBufferInfo* buffer_info, uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2SystemCreateWithAllocator(const Ngs2SystemOption* option, const Ngs2BufferAllocator* allocator, uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2RackCreateWithAllocator(uintptr_t system_handle, uint32_t rack_id, const Ngs2RackOption* option,
|
||||
const Ngs2BufferAllocator* allocator, uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2RackGetVoiceHandle(uintptr_t rack_handle, uint32_t voice_id, uintptr_t* handle);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamHeader* param_list);
|
||||
int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* state, size_t state_size);
|
||||
int KYTY_SYSV_ABI Ngs2SystemRender(uintptr_t system_handle, const Ngs2RenderBufferInfo* buffer_info, uint32_t num_buffer_info);
|
||||
|
||||
} // namespace Ngs2
|
||||
|
||||
} // namespace Kyty::Libs::Audio
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
|
|
@ -58,6 +58,7 @@ int KYTY_SYSV_ABI GraphicsInsertPushMarker(uint32_t* cmd, uint64_t size, co
|
|||
int KYTY_SYSV_ABI GraphicsInsertPopMarker(uint32_t* cmd, uint64_t size);
|
||||
uint64_t KYTY_SYSV_ABI GraphicsGetGpuCoreClockFrequency();
|
||||
int KYTY_SYSV_ABI GraphicsIsUserPaEnabled();
|
||||
void* KYTY_SYSV_ABI GraphicsGetTheTessellationFactorRingBufferBaseAddress();
|
||||
|
||||
int KYTY_SYSV_ABI GraphicsRegisterOwner(uint32_t* owner_handle, const char* name);
|
||||
int KYTY_SYSV_ABI GraphicsRegisterResource(uint32_t* resource_handle, uint32_t owner_handle, const void* memory, size_t size,
|
||||
|
|
|
@ -76,21 +76,23 @@ int KYTY_SYSV_ABI PthreadMutexLock(PthreadMutex* mutex);
|
|||
int KYTY_SYSV_ABI PthreadMutexTrylock(PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI PthreadMutexUnlock(PthreadMutex* mutex);
|
||||
|
||||
Pthread KYTY_SYSV_ABI PthreadSelf();
|
||||
int KYTY_SYSV_ABI PthreadCreate(Pthread* thread, const PthreadAttr* attr, pthread_entry_func_t entry, void* arg, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadDetach(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadJoin(Pthread thread, void** value);
|
||||
int KYTY_SYSV_ABI PthreadCancel(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadSetcancelstate(int state, int* old_state);
|
||||
int KYTY_SYSV_ABI PthreadSetcanceltype(int type, int* old_type);
|
||||
int KYTY_SYSV_ABI PthreadGetprio(Pthread thread, int* prio);
|
||||
int KYTY_SYSV_ABI PthreadSetprio(Pthread thread, int prio);
|
||||
void KYTY_SYSV_ABI PthreadTestcancel();
|
||||
int KYTY_SYSV_ABI PthreadSetaffinity(Pthread thread, KernelCpumask mask);
|
||||
void KYTY_SYSV_ABI PthreadExit(void* value);
|
||||
int KYTY_SYSV_ABI PthreadEqual(Pthread thread1, Pthread thread2);
|
||||
int KYTY_SYSV_ABI PthreadGetname(Pthread thread, char* name);
|
||||
void KYTY_SYSV_ABI PthreadYield();
|
||||
Pthread KYTY_SYSV_ABI PthreadSelf();
|
||||
int KYTY_SYSV_ABI PthreadCreate(Pthread* thread, const PthreadAttr* attr, pthread_entry_func_t entry, void* arg, const char* name);
|
||||
int KYTY_SYSV_ABI PthreadDetach(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadJoin(Pthread thread, void** value);
|
||||
int KYTY_SYSV_ABI PthreadCancel(Pthread thread);
|
||||
int KYTY_SYSV_ABI PthreadSetcancelstate(int state, int* old_state);
|
||||
int KYTY_SYSV_ABI PthreadSetcanceltype(int type, int* old_type);
|
||||
int KYTY_SYSV_ABI PthreadGetprio(Pthread thread, int* prio);
|
||||
int KYTY_SYSV_ABI PthreadSetprio(Pthread thread, int prio);
|
||||
void KYTY_SYSV_ABI PthreadTestcancel();
|
||||
int KYTY_SYSV_ABI PthreadSetaffinity(Pthread thread, KernelCpumask mask);
|
||||
void KYTY_SYSV_ABI PthreadExit(void* value);
|
||||
int KYTY_SYSV_ABI PthreadEqual(Pthread thread1, Pthread thread2);
|
||||
int KYTY_SYSV_ABI PthreadGetname(Pthread thread, char* name);
|
||||
void KYTY_SYSV_ABI PthreadYield();
|
||||
int KYTY_SYSV_ABI PthreadGetthreadid();
|
||||
|
||||
int KYTY_SYSV_ABI KernelUsleep(KernelUseconds microseconds);
|
||||
unsigned int KYTY_SYSV_ABI KernelSleep(unsigned int seconds);
|
||||
int KYTY_SYSV_ABI KernelNanosleep(const KernelTimespec* rqtp, KernelTimespec* rmtp);
|
||||
|
@ -167,6 +169,7 @@ int KYTY_SYSV_ABI pthread_join(LibKernel::Pthread thread, void** value);
|
|||
int KYTY_SYSV_ABI pthread_cond_broadcast(LibKernel::PthreadCond* cond);
|
||||
int KYTY_SYSV_ABI pthread_cond_wait(LibKernel::PthreadCond* cond, LibKernel::PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_mutex_lock(LibKernel::PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_mutex_trylock(LibKernel::PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_mutex_unlock(LibKernel::PthreadMutex* mutex);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_rdlock(LibKernel::PthreadRwlock* rwlock);
|
||||
int KYTY_SYSV_ABI pthread_rwlock_unlock(LibKernel::PthreadRwlock* rwlock);
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_PARAM_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LOADER_PARAM_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
class Image;
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
namespace Kyty::Loader {
|
||||
|
||||
void ParamSfoLoad(const String& file_name);
|
||||
bool ParamSfoGetInt(const char* name, int32_t* value);
|
||||
bool ParamSfoGetString(const char* name, String* value);
|
||||
bool ParamSfoGetString(const char* name, char* value, size_t value_size);
|
||||
Libs::Graphics::Image* ParamSfoGetIcon();
|
||||
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_PARAM_H_ */
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef EMULATOR_INCLUDE_EMULATOR_LOADER_SYSTEMCONTENT_H_
|
||||
#define EMULATOR_INCLUDE_EMULATOR_LOADER_SYSTEMCONTENT_H_
|
||||
|
||||
#include "Kyty/Core/Common.h"
|
||||
#include "Kyty/Core/String.h"
|
||||
|
||||
#include "Emulator/Common.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
namespace Kyty::Libs::Graphics {
|
||||
class Image;
|
||||
} // namespace Kyty::Libs::Graphics
|
||||
|
||||
namespace Kyty::Loader {
|
||||
|
||||
void SystemContentLoadParamSfo(const String& file_name);
|
||||
bool SystemContentParamSfoGetInt(const char* name, int32_t* value);
|
||||
bool SystemContentParamSfoGetString(const char* name, String* value);
|
||||
bool SystemContentParamSfoGetString(const char* name, char* value, size_t value_size);
|
||||
Libs::Graphics::Image* SystemContentGetIcon();
|
||||
bool SystemContentGetChunksNum(uint32_t* num);
|
||||
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
||||
|
||||
#endif /* EMULATOR_INCLUDE_EMULATOR_LOADER_SYSTEMCONTENT_H_ */
|
|
@ -101,6 +101,7 @@ void Init();
|
|||
|
||||
uint64_t Alloc(uint64_t address, uint64_t size, Mode mode);
|
||||
uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t alignment);
|
||||
bool AllocFixed(uint64_t address, uint64_t size, Mode mode);
|
||||
bool Free(uint64_t address);
|
||||
bool Protect(uint64_t address, uint64_t size, Mode mode, Mode* old_mode = nullptr);
|
||||
bool FlushInstructionCache(uint64_t address, uint64_t size);
|
||||
|
|
|
@ -57,6 +57,14 @@ int KYTY_SYSV_ABI HttpSetEpoll(int id, HttpEpollHandle eh, void* user_arg);
|
|||
int KYTY_SYSV_ABI HttpUnsetEpoll(int id);
|
||||
int KYTY_SYSV_ABI HttpSendRequest(int request_id, const void* post_data, size_t size);
|
||||
int KYTY_SYSV_ABI HttpsSetSslCallback(int id, HttpsCallback cbfunc, void* user_arg);
|
||||
int KYTY_SYSV_ABI HttpsDisableOption(int id, uint32_t ssl_flags);
|
||||
int KYTY_SYSV_ABI HttpSetResolveTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetResolveRetry(int id, int32_t retry);
|
||||
int KYTY_SYSV_ABI HttpSetConnectTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetSendTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetRecvTimeOut(int id, uint32_t usec);
|
||||
int KYTY_SYSV_ABI HttpSetAutoRedirect(int id, int enable);
|
||||
int KYTY_SYSV_ABI HttpSetAuthEnabled(int id, int enable);
|
||||
|
||||
} // namespace Http
|
||||
|
||||
|
@ -92,6 +100,7 @@ int KYTY_SYSV_ABI NpSetContentRestriction(const NpContentRestriction* restricti
|
|||
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);
|
||||
int KYTY_SYSV_ABI NpRegisterNpReachabilityStateCallback(void* callback, void* userdata);
|
||||
int KYTY_SYSV_ABI NpGetNpId(int user_id, NpId* np_id);
|
||||
int KYTY_SYSV_ABI NpGetOnlineId(int user_id, NpOnlineId* online_id);
|
||||
int KYTY_SYSV_ABI NpCreateAsyncRequest(const NpCreateAsyncRequestParameter* param);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,6 +18,7 @@
|
|||
#include "Emulator/Kernel/Pthread.h"
|
||||
#include "Emulator/Libs/Errno.h"
|
||||
#include "Emulator/Libs/Libs.h"
|
||||
#include "Emulator/Loader/VirtualMemory.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
|
@ -651,6 +652,21 @@ int KYTY_SYSV_ABI GraphicsIsUserPaEnabled()
|
|||
return 0;
|
||||
}
|
||||
|
||||
void* KYTY_SYSV_ABI GraphicsGetTheTessellationFactorRingBufferBaseAddress()
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
auto addr = Loader::VirtualMemory::AllocAligned(0, 0x20000, Loader::VirtualMemory::Mode::ReadWrite, 256);
|
||||
Loader::VirtualMemory::Free(addr);
|
||||
bool again = Loader::VirtualMemory::AllocFixed(addr, 0x20000, Loader::VirtualMemory::Mode::ReadWrite);
|
||||
EXIT_NOT_IMPLEMENTED(!again);
|
||||
Loader::VirtualMemory::Free(addr);
|
||||
|
||||
printf("\t addr = %016" PRIx64 "\n", addr);
|
||||
|
||||
return reinterpret_cast<void*>(addr);
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI GraphicsRegisterOwner(uint32_t* owner_handle, const char* name)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
|
|
@ -54,6 +54,8 @@ public:
|
|||
void BufferFlush();
|
||||
void BufferWait();
|
||||
|
||||
void RunLock() { m_run_mutex.Lock(); }
|
||||
void RunUnlock() { m_run_mutex.Unlock(); }
|
||||
void Lock() { m_mutex.Lock(); }
|
||||
void Unlock() { m_mutex.Unlock(); }
|
||||
|
||||
|
@ -130,6 +132,7 @@ private:
|
|||
uint32_t m_num_instances = 1;
|
||||
|
||||
Core::Mutex m_mutex;
|
||||
Core::Mutex m_run_mutex;
|
||||
|
||||
CommandBuffer* m_buffer[VK_BUFFERS_NUM] = {};
|
||||
int m_current_buffer = -1;
|
||||
|
@ -340,10 +343,10 @@ uint32_t Gpu::MapComputeQueue(uint32_t pipe_id, uint32_t queue_id, uint32_t* rin
|
|||
|
||||
EXIT_NOT_IMPLEMENTED(v >= 64);
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(m_compute_ring[pipe_id * 8 + i] != nullptr && m_compute_ring[pipe_id * 8 + i]->IsActive());
|
||||
}
|
||||
// for (int i = 0; i < 8; i++)
|
||||
// {
|
||||
// EXIT_NOT_IMPLEMENTED(m_compute_ring[pipe_id * 8 + i] != nullptr && m_compute_ring[pipe_id * 8 + i]->IsActive());
|
||||
// }
|
||||
|
||||
auto* ring = GetRing(v + 1);
|
||||
|
||||
|
@ -761,17 +764,21 @@ void GraphicsRing::ThreadBatchRun(void* data)
|
|||
{
|
||||
CmdBatch buf = ring->GetCmdBatch();
|
||||
|
||||
cp->BufferInit();
|
||||
cp->ResetDeCe();
|
||||
cp->SetFlip(buf.flip);
|
||||
cp->SetSumbitId(++seq);
|
||||
cp->RunLock();
|
||||
{
|
||||
cp->BufferInit();
|
||||
cp->ResetDeCe();
|
||||
cp->SetFlip(buf.flip);
|
||||
cp->SetSumbitId(++seq);
|
||||
|
||||
ring->m_job1.Execute([cp, buf](void* /*unused*/) { cp->Run(buf.draw_buffer.data, buf.draw_buffer.num_dw); });
|
||||
ring->m_job2.Execute([cp, buf](void* /*unused*/) { cp->Run(buf.const_buffer.data, buf.const_buffer.num_dw); });
|
||||
ring->m_job1.Wait();
|
||||
ring->m_job2.Wait();
|
||||
ring->m_job1.Execute([cp, buf](void* /*unused*/) { cp->Run(buf.draw_buffer.data, buf.draw_buffer.num_dw); });
|
||||
ring->m_job2.Execute([cp, buf](void* /*unused*/) { cp->Run(buf.const_buffer.data, buf.const_buffer.num_dw); });
|
||||
ring->m_job1.Wait();
|
||||
ring->m_job2.Wait();
|
||||
|
||||
cp->BufferFlush();
|
||||
cp->BufferFlush();
|
||||
}
|
||||
cp->RunUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -822,14 +829,18 @@ void ComputeRing::ThreadRun(void* data)
|
|||
|
||||
ring->m_mutex.Unlock();
|
||||
|
||||
cp->BufferInit();
|
||||
cp->ResetDeCe();
|
||||
cp->RunLock();
|
||||
{
|
||||
cp->BufferInit();
|
||||
cp->ResetDeCe();
|
||||
|
||||
GraphicsDbgDumpDcb("cc", num_dw, buffer);
|
||||
GraphicsDbgDumpDcb("cc", num_dw, buffer);
|
||||
|
||||
cp->Run(buffer, num_dw);
|
||||
cp->Run(buffer, num_dw);
|
||||
|
||||
cp->BufferFlush();
|
||||
cp->BufferFlush();
|
||||
}
|
||||
cp->RunUnlock();
|
||||
|
||||
ring->m_mutex.Lock();
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include "Emulator/Graphics/Image.h"
|
||||
#include "Emulator/Graphics/Utils.h"
|
||||
#include "Emulator/Graphics/VideoOut.h"
|
||||
#include "Emulator/Loader/Param.h"
|
||||
#include "Emulator/Loader/SystemContent.h"
|
||||
#include "Emulator/Loader/VirtualMemory.h"
|
||||
#include "Emulator/Profiler.h"
|
||||
|
||||
|
@ -2170,7 +2170,7 @@ void WindowUpdateIcon()
|
|||
{
|
||||
EXIT_IF(g_window_ctx == nullptr);
|
||||
|
||||
static Image* icon = Loader::ParamSfoGetIcon();
|
||||
static Image* icon = Loader::SystemContentGetIcon();
|
||||
|
||||
if (icon != nullptr)
|
||||
{
|
||||
|
@ -2186,9 +2186,9 @@ void WindowUpdateTitle()
|
|||
static char title[128];
|
||||
static char title_id[12];
|
||||
static char app_ver[8];
|
||||
static bool has_title = Loader::ParamSfoGetString("TITLE", title, sizeof(title));
|
||||
static bool has_title_id = Loader::ParamSfoGetString("TITLE_ID", title_id, sizeof(title_id));
|
||||
static bool has_app_ver = Loader::ParamSfoGetString("APP_VER", app_ver, sizeof(app_ver));
|
||||
static bool has_title = Loader::SystemContentParamSfoGetString("TITLE", title, sizeof(title));
|
||||
static bool has_title_id = Loader::SystemContentParamSfoGetString("TITLE_ID", title_id, sizeof(title_id));
|
||||
static bool has_app_ver = Loader::SystemContentParamSfoGetString("APP_VER", app_ver, sizeof(app_ver));
|
||||
|
||||
auto fps = String::FromPrintf("%s%s%s%s%s%s[%s] [%s], frame: %d, fps: %f", (has_title ? title : ""), (has_title ? ", " : ""),
|
||||
(has_title_id ? title_id : ""), (has_title_id ? ", " : ""), (has_app_ver ? app_ver : ""),
|
||||
|
|
|
@ -40,7 +40,8 @@ public:
|
|||
Or
|
||||
};
|
||||
|
||||
KernelEventFlagPrivate(const String& name, bool flag, uint64_t bits): m_name(name), m_single_thread(flag), m_bits(bits) {};
|
||||
KernelEventFlagPrivate(const String& name, bool single, bool /*fifo*/, uint64_t bits)
|
||||
: m_name(name), m_single_thread(single), m_bits(bits) {};
|
||||
virtual ~KernelEventFlagPrivate();
|
||||
|
||||
KYTY_CLASS_NO_COPY(KernelEventFlagPrivate);
|
||||
|
@ -270,16 +271,29 @@ int KYTY_SYSV_ABI KernelCreateEventFlag(KernelEventFlag* ef, const char* name, u
|
|||
return KERNEL_ERROR_EINVAL;
|
||||
}
|
||||
|
||||
bool single = false;
|
||||
bool single = true;
|
||||
bool fifo = true;
|
||||
|
||||
switch (attr)
|
||||
{
|
||||
case 0x10: single = true; break;
|
||||
case 0x20: single = false; break;
|
||||
case 0x10:
|
||||
case 0x11:
|
||||
single = true;
|
||||
fifo = true;
|
||||
break;
|
||||
case 0x20:
|
||||
case 0x21:
|
||||
single = false;
|
||||
fifo = true;
|
||||
break;
|
||||
case 0x22:
|
||||
single = false;
|
||||
fifo = false;
|
||||
break;
|
||||
default: EXIT("unknown attr: %u\n", attr);
|
||||
}
|
||||
|
||||
*ef = new KernelEventFlagPrivate(String::FromUtf8(name), single, init_pattern);
|
||||
*ef = new KernelEventFlagPrivate(String::FromUtf8(name), single, fifo, init_pattern);
|
||||
|
||||
printf("\tEventFlag create: %s\n", name);
|
||||
|
||||
|
|
|
@ -619,7 +619,9 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
|
|||
EXIT_IF(g_physical_memory == nullptr);
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(addr == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(flags != 0);
|
||||
EXIT_NOT_IMPLEMENTED(flags != 0 && flags != 0x10);
|
||||
|
||||
bool fixed = (flags == 0x10);
|
||||
|
||||
VirtualMemory::Mode mode = VirtualMemory::Mode::NoAccess;
|
||||
Graphics::GpuMemoryMode gpu_mode = Graphics::GpuMemoryMode::NoAccess;
|
||||
|
@ -642,9 +644,24 @@ int KYTY_SYSV_ABI KernelMapDirectMemory(void** addr, size_t len, int prot, int f
|
|||
default: EXIT("unknown prot: %d\n", prot);
|
||||
}
|
||||
|
||||
auto in_addr = reinterpret_cast<uint64_t>(*addr);
|
||||
auto out_addr = VirtualMemory::AllocAligned(in_addr, len, mode, alignment);
|
||||
*addr = reinterpret_cast<void*>(out_addr);
|
||||
auto in_addr = reinterpret_cast<uint64_t>(*addr);
|
||||
uint64_t out_addr = 0;
|
||||
|
||||
if (fixed)
|
||||
{
|
||||
EXIT_NOT_IMPLEMENTED(in_addr == 0);
|
||||
EXIT_NOT_IMPLEMENTED((in_addr & (alignment - 1)) != 0);
|
||||
|
||||
if (VirtualMemory::AllocFixed(in_addr, len, mode))
|
||||
{
|
||||
out_addr = in_addr;
|
||||
}
|
||||
} else
|
||||
{
|
||||
out_addr = VirtualMemory::AllocAligned(in_addr, len, mode, alignment);
|
||||
}
|
||||
|
||||
*addr = reinterpret_cast<void*>(out_addr);
|
||||
|
||||
printf("\t in_addr = 0x%016" PRIx64 "\n", in_addr);
|
||||
printf("\t out_addr = 0x%016" PRIx64 "\n", out_addr);
|
||||
|
|
|
@ -2287,6 +2287,13 @@ void KYTY_SYSV_ABI PthreadYield()
|
|||
sched_yield();
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PthreadGetthreadid()
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
return Core::Thread::GetThreadIdUnique();
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI KernelClockGetres(KernelClockid clock_id, KernelTimespec* tp)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
@ -2592,6 +2599,13 @@ int KYTY_SYSV_ABI pthread_mutex_lock(LibKernel::PthreadMutex* mutex)
|
|||
return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexLock(mutex));
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI pthread_mutex_trylock(LibKernel::PthreadMutex* mutex)
|
||||
{
|
||||
// PRINT_NAME();
|
||||
|
||||
return POSIX_PTHREAD_CALL(LibKernel::PthreadMutexTrylock(mutex));
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI pthread_mutex_unlock(LibKernel::PthreadMutex* mutex)
|
||||
{
|
||||
// PRINT_NAME();
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "Emulator/Kernel/Memory.h"
|
||||
#include "Emulator/Kernel/Pthread.h"
|
||||
#include "Emulator/Libs/Libs.h"
|
||||
#include "Emulator/Loader/Param.h"
|
||||
#include "Emulator/Loader/RuntimeLinker.h"
|
||||
#include "Emulator/Loader/SystemContent.h"
|
||||
#include "Emulator/Loader/Timer.h"
|
||||
#include "Emulator/Loader/VirtualMemory.h"
|
||||
#include "Emulator/Network.h"
|
||||
|
@ -225,7 +225,7 @@ KYTY_SCRIPT_FUNC(kyty_load_param_sfo_func)
|
|||
|
||||
if (!file_name.IsEmpty())
|
||||
{
|
||||
Loader::ParamSfoLoad(Scripts::ArgGetVar(0).ToString());
|
||||
Loader::SystemContentLoadParamSfo(Scripts::ArgGetVar(0).ToString());
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#include "Emulator/Common.h"
|
||||
#include "Emulator/Libs/Errno.h"
|
||||
#include "Emulator/Libs/Libs.h"
|
||||
#include "Emulator/Loader/Param.h"
|
||||
#include "Emulator/Loader/SymbolDatabase.h"
|
||||
#include "Emulator/Loader/SystemContent.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
|
@ -84,10 +84,10 @@ int KYTY_SYSV_ABI AppContentAppParamGetInt(uint32_t param_id, int32_t* value)
|
|||
*value = 3;
|
||||
found = true;
|
||||
break;
|
||||
case 1: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_1", value); break;
|
||||
case 2: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_2", value); break;
|
||||
case 3: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_3", value); break;
|
||||
case 4: found = Loader::ParamSfoGetInt("USER_DEFINED_PARAM_4", value); break;
|
||||
case 1: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_1", value); break;
|
||||
case 2: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_2", value); break;
|
||||
case 3: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_3", value); break;
|
||||
case 4: found = Loader::SystemContentParamSfoGetInt("USER_DEFINED_PARAM_4", value); break;
|
||||
default: EXIT("unknown param_id: %u\n", param_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ LIB_DEFINE(InitAudio_1_AudioOut)
|
|||
LIB_FUNC("w3PdaSTSwGE", AudioOut::AudioOutOutputs);
|
||||
LIB_FUNC("QOQtbeDqsT4", AudioOut::AudioOutOutput);
|
||||
LIB_FUNC("s1--uE9mBFw", AudioOut::AudioOutClose);
|
||||
LIB_FUNC("GrQ9s4IrNaQ", AudioOut::AudioOutGetPortState);
|
||||
}
|
||||
|
||||
} // namespace LibAudioOut
|
||||
|
@ -85,6 +86,45 @@ LIB_DEFINE(InitAudio_1_AvPlayer)
|
|||
|
||||
} // namespace LibAvPlayer
|
||||
|
||||
namespace LibAudio3d {
|
||||
|
||||
LIB_VERSION("Audio3d", 1, "Audio3d", 1, 1);
|
||||
|
||||
namespace Audio3d = Audio::Audio3d;
|
||||
|
||||
LIB_DEFINE(InitAudio_1_Audio3d)
|
||||
{
|
||||
LIB_FUNC("UmCvjSmuZIw", Audio3d::Audio3dInitialize);
|
||||
LIB_FUNC("Im+jOoa5WAI", Audio3d::Audio3dGetDefaultOpenParameters);
|
||||
LIB_FUNC("XeDDK0xJWQA", Audio3d::Audio3dPortOpen);
|
||||
LIB_FUNC("Yq9bfUQ0uJg", Audio3d::Audio3dPortSetAttribute);
|
||||
LIB_FUNC("YaaDbDwKpFM", Audio3d::Audio3dPortGetQueueLevel);
|
||||
LIB_FUNC("lw0qrdSjZt8", Audio3d::Audio3dPortAdvance);
|
||||
LIB_FUNC("VEVhZ9qd4ZY", Audio3d::Audio3dPortPush);
|
||||
}
|
||||
|
||||
} // namespace LibAudio3d
|
||||
|
||||
namespace LibNgs2 {
|
||||
|
||||
LIB_VERSION("Ngs2", 1, "Ngs2", 1, 1);
|
||||
|
||||
namespace Ngs2 = Audio::Ngs2;
|
||||
|
||||
LIB_DEFINE(InitAudio_1_Ngs2)
|
||||
{
|
||||
LIB_FUNC("mPYgU4oYpuY", Ngs2::Ngs2SystemCreateWithAllocator);
|
||||
LIB_FUNC("U546k6orxQo", Ngs2::Ngs2RackCreateWithAllocator);
|
||||
LIB_FUNC("cLV4aiT9JpA", Ngs2::Ngs2RackCreate);
|
||||
LIB_FUNC("0eFLVCfWVds", Ngs2::Ngs2RackQueryBufferSize);
|
||||
LIB_FUNC("MwmHz8pAdAo", Ngs2::Ngs2RackGetVoiceHandle);
|
||||
LIB_FUNC("uu94irFOGpA", Ngs2::Ngs2VoiceControl);
|
||||
LIB_FUNC("-TOuuAQ-buE", Ngs2::Ngs2VoiceGetState);
|
||||
LIB_FUNC("i0VnXM-C9fc", Ngs2::Ngs2SystemRender);
|
||||
}
|
||||
|
||||
} // namespace LibNgs2
|
||||
|
||||
LIB_DEFINE(InitAudio_1)
|
||||
{
|
||||
LibAudioOut::InitAudio_1_AudioOut(s);
|
||||
|
@ -92,6 +132,8 @@ LIB_DEFINE(InitAudio_1)
|
|||
LibVoiceQoS::InitAudio_1_VoiceQoS(s);
|
||||
LibAjm::InitAudio_1_Ajm(s);
|
||||
LibAvPlayer::InitAudio_1_AvPlayer(s);
|
||||
LibAudio3d::InitAudio_1_Audio3d(s);
|
||||
LibNgs2::InitAudio_1_Ngs2(s);
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs
|
||||
|
|
|
@ -47,6 +47,7 @@ LIB_DEFINE(InitGraphicsDriver_1)
|
|||
LIB_FUNC("nvEwfYAImTs", Graphics::GraphicsRegisterResource);
|
||||
LIB_FUNC("Fwvh++m9IQI", Graphics::GraphicsGetGpuCoreClockFrequency);
|
||||
LIB_FUNC("jg33rEKLfVs", Graphics::GraphicsIsUserPaEnabled);
|
||||
LIB_FUNC("ln33zjBrfjk", Graphics::GraphicsGetTheTessellationFactorRingBufferBaseAddress);
|
||||
}
|
||||
|
||||
} // namespace Kyty::Libs
|
||||
|
|
|
@ -460,6 +460,7 @@ LIB_DEFINE(InitLibKernel_1_Posix)
|
|||
LIB_FUNC("OxhIB8LB-PQ", Posix::pthread_create);
|
||||
LIB_FUNC("h9CcP3J0oVM", Posix::pthread_join);
|
||||
LIB_FUNC("7H0iTOciTLo", Posix::pthread_mutex_lock);
|
||||
LIB_FUNC("K-jXhbt2gn4", Posix::pthread_mutex_trylock);
|
||||
LIB_FUNC("2Z+PpY6CaJg", Posix::pthread_mutex_unlock);
|
||||
LIB_FUNC("ttHNfU+qDBU", Posix::pthread_mutex_init);
|
||||
LIB_FUNC("dQHWEsJtoE4", Posix::pthread_mutexattr_init);
|
||||
|
@ -525,6 +526,7 @@ LIB_DEFINE(InitLibKernel_1_EventFlag)
|
|||
{
|
||||
LIB_FUNC("BpFoboUJoZU", EventFlag::KernelCreateEventFlag);
|
||||
LIB_FUNC("JTvBflhYazQ", EventFlag::KernelWaitEventFlag);
|
||||
LIB_FUNC("IOnSvHzqu6A", EventFlag::KernelSetEventFlag);
|
||||
}
|
||||
|
||||
LIB_DEFINE(InitLibKernel_1_Semaphore)
|
||||
|
@ -557,6 +559,7 @@ LIB_DEFINE(InitLibKernel_1_Pthread)
|
|||
LIB_FUNC("1tKyG7RlMJo", LibKernel::PthreadGetprio);
|
||||
LIB_FUNC("W0Hpm2X0uPE", LibKernel::PthreadSetprio);
|
||||
LIB_FUNC("T72hz6ffq08", LibKernel::PthreadYield);
|
||||
LIB_FUNC("EI-5-jlq2dE", LibKernel::PthreadGetthreadid);
|
||||
|
||||
LIB_FUNC("62KCwEMmzcM", LibKernel::PthreadAttrDestroy);
|
||||
LIB_FUNC("x1X76arYMxU", LibKernel::PthreadAttrGet);
|
||||
|
@ -568,6 +571,7 @@ LIB_DEFINE(InitLibKernel_1_Pthread)
|
|||
LIB_FUNC("txHtngJ+eyc", LibKernel::PthreadAttrGetguardsize);
|
||||
LIB_FUNC("UTXzJbWhhTE", LibKernel::PthreadAttrSetstacksize);
|
||||
LIB_FUNC("-Wreprtu0Qs", LibKernel::PthreadAttrSetdetachstate);
|
||||
LIB_FUNC("El+cQ20DynU", LibKernel::PthreadAttrSetguardsize);
|
||||
LIB_FUNC("eXbUSpEaTsA", LibKernel::PthreadAttrSetinheritsched);
|
||||
LIB_FUNC("DzES9hQF4f4", LibKernel::PthreadAttrSetschedparam);
|
||||
LIB_FUNC("4+h9EzwKF4I", LibKernel::PthreadAttrSetschedpolicy);
|
||||
|
@ -590,8 +594,11 @@ LIB_DEFINE(InitLibKernel_1_Pthread)
|
|||
|
||||
LIB_FUNC("QBi7HCK03hw", LibKernel::KernelClockGettime);
|
||||
LIB_FUNC("ejekcaNQNq0", LibKernel::KernelGettimeofday);
|
||||
LIB_FUNC("-2IRUCO--PM", LibKernel::KernelReadTsc);
|
||||
LIB_FUNC("1j3S3n-tTW4", LibKernel::KernelGetTscFrequency);
|
||||
LIB_FUNC("4J2sUJmuHZQ", LibKernel::KernelGetProcessTime);
|
||||
LIB_FUNC("BNowx2l588E", LibKernel::KernelGetProcessTimeCounterFrequency);
|
||||
LIB_FUNC("fgxnMeTNUtY", LibKernel::KernelGetProcessTimeCounter);
|
||||
|
||||
LIB_FUNC("7H0iTOciTLo", Posix::pthread_mutex_lock);
|
||||
LIB_FUNC("2Z+PpY6CaJg", Posix::pthread_mutex_unlock);
|
||||
|
|
|
@ -100,6 +100,7 @@ LIB_DEFINE(InitNet_1_Http)
|
|||
LIB_FUNC("4I8vEpuEhZ8", Http::HttpDeleteTemplate);
|
||||
LIB_FUNC("s2-NPIvz+iA", Http::HttpSetNonblock);
|
||||
LIB_FUNC("htyBOoWeS58", Http::HttpsSetSslCallback);
|
||||
LIB_FUNC("mSQCxzWTwVI", Http::HttpsDisableOption);
|
||||
LIB_FUNC("6381dWF+xsQ", Http::HttpCreateEpoll);
|
||||
LIB_FUNC("wYhXVfS2Et4", Http::HttpDestroyEpoll);
|
||||
LIB_FUNC("-xm7kZQNpHI", Http::HttpSetEpoll);
|
||||
|
@ -110,6 +111,13 @@ LIB_DEFINE(InitNet_1_Http)
|
|||
LIB_FUNC("qe7oZ+v4PWA", Http::HttpDeleteRequest);
|
||||
LIB_FUNC("EY28T2bkN7k", Http::HttpAddRequestHeader);
|
||||
LIB_FUNC("1e2BNwI-XzE", Http::HttpSendRequest);
|
||||
LIB_FUNC("Tc-hAYDKtQc", Http::HttpSetResolveTimeOut);
|
||||
LIB_FUNC("K1d1LqZRQHQ", Http::HttpSetResolveRetry);
|
||||
LIB_FUNC("0S9tTH0uqTU", Http::HttpSetConnectTimeOut);
|
||||
LIB_FUNC("xegFfZKBVlw", Http::HttpSetSendTimeOut);
|
||||
LIB_FUNC("yigr4V0-HTM", Http::HttpSetRecvTimeOut);
|
||||
LIB_FUNC("T-mGo9f3Pu4", Http::HttpSetAutoRedirect);
|
||||
LIB_FUNC("qFg2SuyTJJY", Http::HttpSetAuthEnabled);
|
||||
}
|
||||
|
||||
} // namespace LibHttp
|
||||
|
@ -146,6 +154,7 @@ LIB_DEFINE(InitNet_1_NpManager)
|
|||
LIB_FUNC("VfRSmPmj8Q8", NpManager::NpRegisterStateCallback);
|
||||
LIB_FUNC("uFJpaKNBAj4", NpManager::NpRegisterGamePresenceCallback);
|
||||
LIB_FUNC("GImICnh+boA", NpManager::NpRegisterPlusEventCallback);
|
||||
LIB_FUNC("hw5KNqAAels", NpManager::NpRegisterNpReachabilityStateCallback);
|
||||
LIB_FUNC("p-o74CnoNzY", NpManager::NpGetNpId);
|
||||
LIB_FUNC("XDncXQIJUSk", NpManager::NpGetOnlineId);
|
||||
LIB_FUNC("eiqMCt9UshI", NpManager::NpCreateAsyncRequest);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "Emulator/Libs/Errno.h"
|
||||
#include "Emulator/Libs/Libs.h"
|
||||
#include "Emulator/Loader/SymbolDatabase.h"
|
||||
#include "Emulator/Loader/SystemContent.h"
|
||||
|
||||
#ifdef KYTY_EMU_ENABLED
|
||||
|
||||
|
@ -15,6 +16,8 @@ LIB_VERSION("PlayGo", 1, "PlayGo", 1, 0);
|
|||
|
||||
namespace PlayGo {
|
||||
|
||||
static uint32_t g_chunks_num = 0;
|
||||
|
||||
struct PlayGoInitParams
|
||||
{
|
||||
const void* buf_addr;
|
||||
|
@ -35,6 +38,13 @@ int KYTY_SYSV_ABI PlayGoInitialize(const PlayGoInitParams* init)
|
|||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoTerminate()
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoOpen(int* out_handle, const void* param)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
@ -44,6 +54,21 @@ int KYTY_SYSV_ABI PlayGoOpen(int* out_handle, const void* param)
|
|||
|
||||
*out_handle = 1;
|
||||
|
||||
if (!Loader::SystemContentGetChunksNum(&g_chunks_num))
|
||||
{
|
||||
printf("Warning: assume that chunks count is 1\n");
|
||||
g_chunks_num = 1;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI PlayGoClose(int handle)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(handle != 1);
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
@ -56,13 +81,14 @@ int KYTY_SYSV_ABI PlayGoGetLocus(int handle, const uint16_t* chunk_ids, uint32_t
|
|||
EXIT_NOT_IMPLEMENTED(handle != 1);
|
||||
EXIT_NOT_IMPLEMENTED(chunk_ids == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(out_loci == nullptr);
|
||||
EXIT_NOT_IMPLEMENTED(number_of_entries != 1);
|
||||
// EXIT_NOT_IMPLEMENTED(number_of_entries != 1);
|
||||
EXIT_NOT_IMPLEMENTED(g_chunks_num == 0);
|
||||
|
||||
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)
|
||||
if (chunk_ids[i] <= g_chunks_num)
|
||||
{
|
||||
out_loci[i] = 3;
|
||||
} else
|
||||
|
@ -79,7 +105,9 @@ int KYTY_SYSV_ABI PlayGoGetLocus(int handle, const uint16_t* chunk_ids, uint32_t
|
|||
LIB_DEFINE(InitPlayGo_1)
|
||||
{
|
||||
LIB_FUNC("ts6GlZOKRrE", PlayGo::PlayGoInitialize);
|
||||
LIB_FUNC("MPe0EeBGM-E", PlayGo::PlayGoTerminate);
|
||||
LIB_FUNC("M1Gma1ocrGE", PlayGo::PlayGoOpen);
|
||||
LIB_FUNC("Uco1I0dlDi8", PlayGo::PlayGoClose);
|
||||
LIB_FUNC("uWIYLFkkwqk", PlayGo::PlayGoGetLocus);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include "Emulator/Loader/Param.h"
|
||||
#include "Emulator/Loader/SystemContent.h"
|
||||
|
||||
#include "Kyty/Core/ByteBuffer.h"
|
||||
#include "Kyty/Core/Common.h"
|
||||
|
@ -52,10 +52,36 @@ private:
|
|||
char* m_name_tbl = nullptr;
|
||||
};
|
||||
|
||||
class PlayGo
|
||||
{
|
||||
public:
|
||||
PlayGo() = default;
|
||||
virtual ~PlayGo();
|
||||
|
||||
KYTY_CLASS_NO_COPY(PlayGo);
|
||||
|
||||
void Open(const String& file_name);
|
||||
void Close();
|
||||
|
||||
bool IsValid();
|
||||
|
||||
bool GetChunksNum(uint32_t* num);
|
||||
|
||||
void DbgPrint();
|
||||
|
||||
private:
|
||||
Core::File m_f;
|
||||
Core::Mutex m_mutex;
|
||||
bool m_opened = false;
|
||||
uint16_t m_chunks_num = 0;
|
||||
};
|
||||
|
||||
struct SystemContent
|
||||
{
|
||||
String psf_path;
|
||||
Psf psf;
|
||||
String playgo_path;
|
||||
PlayGo playgo;
|
||||
String icon_path;
|
||||
Libs::Graphics::Image* icon = nullptr;
|
||||
};
|
||||
|
@ -247,7 +273,82 @@ bool Psf::GetParamString(const char* name, char* value, size_t value_size)
|
|||
return false;
|
||||
}
|
||||
|
||||
void ParamSfoLoad(const String& file_name)
|
||||
PlayGo::~PlayGo()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void PlayGo::Open(const String& file_name)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
Close();
|
||||
|
||||
m_f.Open(file_name, Core::File::Mode::Read);
|
||||
|
||||
if (m_f.IsInvalid())
|
||||
{
|
||||
printf("Can't open %s\n", file_name.C_Str());
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t magic1 = 0;
|
||||
|
||||
m_f.Read(&magic1, 4);
|
||||
|
||||
if (magic1 != 0x6f676c70)
|
||||
{
|
||||
printf("invalid file: magic1 = %08" PRIx32 "\n", magic1);
|
||||
return;
|
||||
}
|
||||
|
||||
m_f.Seek(10);
|
||||
m_f.Read(&m_chunks_num, 2);
|
||||
|
||||
m_opened = true;
|
||||
}
|
||||
|
||||
void PlayGo::Close()
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
if (!m_f.IsInvalid())
|
||||
{
|
||||
m_f.Close();
|
||||
}
|
||||
m_opened = false;
|
||||
}
|
||||
|
||||
bool PlayGo::IsValid()
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
return m_opened;
|
||||
}
|
||||
|
||||
bool PlayGo::GetChunksNum(uint32_t* num)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
if (m_opened)
|
||||
{
|
||||
*num = m_chunks_num;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PlayGo::DbgPrint()
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
if (m_opened)
|
||||
{
|
||||
printf("PlayGo: chunks num = %" PRIu16 "\n", m_chunks_num);
|
||||
}
|
||||
}
|
||||
|
||||
void SystemContentLoadParamSfo(const String& file_name)
|
||||
{
|
||||
auto* sc = Core::Singleton<SystemContent>::Instance();
|
||||
|
||||
|
@ -277,9 +378,17 @@ void ParamSfoLoad(const String& file_name)
|
|||
{
|
||||
sc->icon = nullptr;
|
||||
}
|
||||
|
||||
sc->playgo_path = file_name.DirectoryWithoutFilename() + U"playgo-chunk.dat";
|
||||
sc->playgo.Open(sc->playgo_path);
|
||||
|
||||
if (sc->playgo.IsValid())
|
||||
{
|
||||
sc->playgo.DbgPrint();
|
||||
}
|
||||
}
|
||||
|
||||
bool ParamSfoGetInt(const char* name, int32_t* value)
|
||||
bool SystemContentParamSfoGetInt(const char* name, int32_t* value)
|
||||
{
|
||||
if (name == nullptr || value == nullptr)
|
||||
{
|
||||
|
@ -291,7 +400,7 @@ bool ParamSfoGetInt(const char* name, int32_t* value)
|
|||
return sc->psf.GetParamInt(name, value);
|
||||
}
|
||||
|
||||
bool ParamSfoGetString(const char* name, String* value)
|
||||
bool SystemContentParamSfoGetString(const char* name, String* value)
|
||||
{
|
||||
if (name == nullptr || value == nullptr)
|
||||
{
|
||||
|
@ -303,7 +412,7 @@ bool ParamSfoGetString(const char* name, String* value)
|
|||
return sc->psf.GetParamString(name, value);
|
||||
}
|
||||
|
||||
bool ParamSfoGetString(const char* name, char* value, size_t value_size)
|
||||
bool SystemContentParamSfoGetString(const char* name, char* value, size_t value_size)
|
||||
{
|
||||
if (name == nullptr || value == nullptr)
|
||||
{
|
||||
|
@ -315,13 +424,25 @@ bool ParamSfoGetString(const char* name, char* value, size_t value_size)
|
|||
return sc->psf.GetParamString(name, value, value_size);
|
||||
}
|
||||
|
||||
Libs::Graphics::Image* ParamSfoGetIcon()
|
||||
Libs::Graphics::Image* SystemContentGetIcon()
|
||||
{
|
||||
auto* sc = Core::Singleton<SystemContent>::Instance();
|
||||
|
||||
return sc->icon;
|
||||
}
|
||||
|
||||
bool SystemContentGetChunksNum(uint32_t* num)
|
||||
{
|
||||
if (num == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* sc = Core::Singleton<SystemContent>::Instance();
|
||||
|
||||
return sc->playgo.GetChunksNum(num);
|
||||
}
|
||||
|
||||
} // namespace Kyty::Loader
|
||||
|
||||
#endif // KYTY_EMU_ENABLED
|
|
@ -389,6 +389,30 @@ uint64_t AllocAligned(uint64_t address, uint64_t size, Mode mode, uint64_t align
|
|||
return ptr;
|
||||
}
|
||||
|
||||
bool AllocFixed(uint64_t address, uint64_t size, Mode mode)
|
||||
{
|
||||
auto ptr = reinterpret_cast<uintptr_t>(VirtualAlloc(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), size,
|
||||
static_cast<DWORD>(MEM_COMMIT) | static_cast<DWORD>(MEM_RESERVE),
|
||||
get_protection_flag(mode)));
|
||||
if (ptr == 0)
|
||||
{
|
||||
auto err = static_cast<uint32_t>(GetLastError());
|
||||
|
||||
printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ptr != address)
|
||||
{
|
||||
printf("VirtualAlloc() failed: wrong address\n");
|
||||
VirtualFree(reinterpret_cast<LPVOID>(ptr), 0, MEM_RELEASE);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Free(uint64_t address)
|
||||
{
|
||||
if (VirtualFree(reinterpret_cast<LPVOID>(static_cast<uintptr_t>(address)), 0, MEM_RELEASE) == 0)
|
||||
|
|
|
@ -88,6 +88,7 @@ public:
|
|||
bool HttpDeleteTemplate(Id tmpl_id);
|
||||
bool HttpSetNonblock(Id id, bool enable);
|
||||
bool HttpsSetSslCallback(Id id, HttpsCallback cbfunc, void* user_arg);
|
||||
bool HttpsDisableOption(Id id, uint32_t ssl_flags);
|
||||
bool HttpAddRequestHeader(Id id, const char* name, const char* value, bool add);
|
||||
bool HttpValid(Id http_ctx_id);
|
||||
bool HttpValidTemplate(Id tmpl_id);
|
||||
|
@ -97,6 +98,13 @@ public:
|
|||
bool HttpDeleteConnection(Id conn_id);
|
||||
Id HttpCreateRequestWithURL2(Id conn_id, const char* method, const char* url, uint64_t content_length);
|
||||
bool HttpDeleteRequest(Id req_id);
|
||||
bool HttpSetResolveTimeOut(Id id, uint32_t usec);
|
||||
bool HttpSetResolveRetry(Id id, int32_t retry);
|
||||
bool HttpSetConnectTimeOut(Id id, uint32_t usec);
|
||||
bool HttpSetSendTimeOut(Id id, uint32_t usec);
|
||||
bool HttpSetRecvTimeOut(Id id, uint32_t usec);
|
||||
bool HttpSetAutoRedirect(Id id, int enable);
|
||||
bool HttpSetAuthEnabled(Id id, int enable);
|
||||
|
||||
private:
|
||||
struct Pool
|
||||
|
@ -128,31 +136,41 @@ private:
|
|||
|
||||
struct HttpBase
|
||||
{
|
||||
bool used = false;
|
||||
bool nonblock = false;
|
||||
Vector<HttpHeader> headers;
|
||||
HttpsCallback ssl_cbfunc = nullptr;
|
||||
void* ssl_user_arg = nullptr;
|
||||
bool used = false;
|
||||
bool nonblock = false;
|
||||
bool auto_redirect = true;
|
||||
bool auth_enabled = true;
|
||||
HttpsCallback ssl_cbfunc = nullptr;
|
||||
void* ssl_user_arg = nullptr;
|
||||
uint32_t ssl_flags = 0xA7;
|
||||
int http_ctx_id = 0;
|
||||
uint32_t resolve_timeout = 1'000000;
|
||||
int32_t resolve_retry = 4;
|
||||
uint32_t connect_timeout = 30'000000;
|
||||
uint32_t send_timeout = 120'000000;
|
||||
uint32_t recv_timeout = 120'000000;
|
||||
};
|
||||
|
||||
struct HttpTemplate: public HttpBase
|
||||
{
|
||||
int http_ctx_id = 0;
|
||||
String user_agent;
|
||||
int http_ver = 0;
|
||||
bool is_auto_proxy_conf = true;
|
||||
};
|
||||
|
||||
struct HttpConnection: public HttpBase
|
||||
struct HttpConnection: public HttpTemplate
|
||||
{
|
||||
int tmpl_id = 0;
|
||||
explicit HttpConnection(const HttpTemplate& tmpl): HttpTemplate(tmpl) {}
|
||||
// int tmpl_id = 0;
|
||||
String url;
|
||||
bool enable_keep_alive = false;
|
||||
};
|
||||
|
||||
struct HttpRequest: public HttpBase
|
||||
struct HttpRequest: public HttpConnection
|
||||
{
|
||||
int conn_id = 0;
|
||||
explicit HttpRequest(HttpConnection& conn): HttpConnection(conn) {}
|
||||
// int conn_id = 0;
|
||||
String method;
|
||||
String url;
|
||||
uint64_t content_length = 0;
|
||||
|
@ -358,11 +376,11 @@ Network::Id Network::HttpCreateConnectionWithURL(Id tmpl_id, const char* url, bo
|
|||
|
||||
if (HttpValidTemplate(tmpl_id))
|
||||
{
|
||||
HttpConnection cn {};
|
||||
HttpConnection cn(m_templates[tmpl_id.GetId()]);
|
||||
cn.used = true;
|
||||
cn.enable_keep_alive = enable_keep_alive;
|
||||
cn.url = String::FromUtf8(url);
|
||||
cn.tmpl_id = tmpl_id.ToInt();
|
||||
// cn.tmpl_id = tmpl_id.ToInt();
|
||||
|
||||
int index = 0;
|
||||
for (auto& t: m_connections)
|
||||
|
@ -405,11 +423,11 @@ Network::Id Network::HttpCreateRequestWithURL2(Id conn_id, const char* method, c
|
|||
|
||||
if (HttpValidConnection(conn_id))
|
||||
{
|
||||
HttpRequest cn {};
|
||||
cn.used = true;
|
||||
cn.method = String::FromUtf8(method);
|
||||
cn.url = String::FromUtf8(url);
|
||||
cn.conn_id = conn_id.ToInt();
|
||||
HttpRequest cn(m_connections[conn_id.GetId()]);
|
||||
cn.used = true;
|
||||
cn.method = String::FromUtf8(method);
|
||||
cn.url = String::FromUtf8(url);
|
||||
// cn.conn_id = conn_id.ToInt();
|
||||
cn.content_length = content_length;
|
||||
|
||||
int index = 0;
|
||||
|
@ -514,6 +532,32 @@ bool Network::HttpsSetSslCallback(Id id, HttpsCallback cbfunc, void* user_arg)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpsDisableOption(Id id, uint32_t ssl_flags)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
} else if (HttpValidRequest(id))
|
||||
{
|
||||
base = &m_requests[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->ssl_flags &= ~ssl_flags;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpAddRequestHeader(Id id, const char* name, const char* value, bool add)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
@ -553,6 +597,182 @@ bool Network::HttpAddRequestHeader(Id id, const char* name, const char* value, b
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpSetResolveTimeOut(Id id, uint32_t usec)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->resolve_timeout = usec;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpSetResolveRetry(Id id, int32_t retry)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->resolve_retry = retry;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpSetConnectTimeOut(Id id, uint32_t usec)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
} else if (HttpValidRequest(id))
|
||||
{
|
||||
base = &m_requests[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->connect_timeout = usec;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpSetSendTimeOut(Id id, uint32_t usec)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
} else if (HttpValidRequest(id))
|
||||
{
|
||||
base = &m_requests[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->send_timeout = usec;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpSetRecvTimeOut(Id id, uint32_t usec)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
} else if (HttpValidRequest(id))
|
||||
{
|
||||
base = &m_requests[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->recv_timeout = usec;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpSetAutoRedirect(Id id, int enable)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
} else if (HttpValidRequest(id))
|
||||
{
|
||||
base = &m_requests[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->auto_redirect = (enable != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Network::HttpSetAuthEnabled(Id id, int enable)
|
||||
{
|
||||
Core::LockGuard lock(m_mutex);
|
||||
|
||||
HttpBase* base = nullptr;
|
||||
|
||||
if (HttpValidTemplate(id))
|
||||
{
|
||||
base = &m_templates[id.GetId()];
|
||||
} else if (HttpValidConnection(id))
|
||||
{
|
||||
base = &m_connections[id.GetId()];
|
||||
} else if (HttpValidRequest(id))
|
||||
{
|
||||
base = &m_requests[id.GetId()];
|
||||
}
|
||||
|
||||
if (base != nullptr)
|
||||
{
|
||||
base->auth_enabled = (enable != 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace Net {
|
||||
|
||||
LIB_NAME("Net", "Net");
|
||||
|
@ -810,6 +1030,126 @@ int KYTY_SYSV_ABI HttpsSetSslCallback(int id, HttpsCallback cbfunc, void* user_a
|
|||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpsDisableOption(int id, uint32_t ssl_flags)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t ssl_flags = %u\n", ssl_flags);
|
||||
|
||||
if (!g_net->HttpsDisableOption(Network::Id(id), ssl_flags))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpSetResolveTimeOut(int id, uint32_t usec)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t usec = %u\n", usec);
|
||||
|
||||
if (!g_net->HttpSetResolveTimeOut(Network::Id(id), usec))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpSetResolveRetry(int id, int32_t retry)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t retry = %d\n", retry);
|
||||
|
||||
if (!g_net->HttpSetResolveRetry(Network::Id(id), retry))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpSetConnectTimeOut(int id, uint32_t usec)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t usec = %u\n", usec);
|
||||
|
||||
if (!g_net->HttpSetConnectTimeOut(Network::Id(id), usec))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpSetSendTimeOut(int id, uint32_t usec)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t usec = %u\n", usec);
|
||||
|
||||
if (!g_net->HttpSetSendTimeOut(Network::Id(id), usec))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpSetRecvTimeOut(int id, uint32_t usec)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t usec = %u\n", usec);
|
||||
|
||||
if (!g_net->HttpSetRecvTimeOut(Network::Id(id), usec))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpSetAutoRedirect(int id, int enable)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t enable = %d\n", enable);
|
||||
|
||||
if (!g_net->HttpSetAutoRedirect(Network::Id(id), enable))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpSetAuthEnabled(int id, int enable)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
printf("\t id = %d\n", id);
|
||||
printf("\t enable = %d\n", enable);
|
||||
|
||||
if (!g_net->HttpSetAuthEnabled(Network::Id(id), enable))
|
||||
{
|
||||
return HTTP_ERROR_INVALID_ID;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI HttpAddRequestHeader(int id, const char* name, const char* value, uint32_t mode)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
@ -1218,6 +1558,13 @@ int KYTY_SYSV_ABI NpRegisterPlusEventCallback(void* /*callback*/, void* /*userda
|
|||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI NpRegisterNpReachabilityStateCallback(void* /*callback*/, void* /*userdata*/)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int KYTY_SYSV_ABI NpGetNpId(int user_id, NpId* np_id)
|
||||
{
|
||||
PRINT_NAME();
|
||||
|
|
Loading…
Reference in New Issue