From 16baf5cc187e241fecac8af9f1ed5412a184f84b Mon Sep 17 00:00:00 2001 From: InoriRus Date: Tue, 7 Jun 2022 16:19:01 +1000 Subject: [PATCH] more APIs --- appveyor.yml | 2 +- source/CMakeLists.txt | 2 +- source/emulator/include/Emulator/Audio.h | 39 + .../include/Emulator/Graphics/Graphics.h | 1 + .../include/Emulator/Kernel/Pthread.h | 33 +- .../emulator/include/Emulator/Loader/Param.h | 27 - .../include/Emulator/Loader/SystemContent.h | 28 + .../include/Emulator/Loader/VirtualMemory.h | 1 + source/emulator/include/Emulator/Network.h | 9 + source/emulator/src/Audio.cpp | 1051 ++++++++++++++++- source/emulator/src/Graphics/Graphics.cpp | 16 + source/emulator/src/Graphics/GraphicsRun.cpp | 47 +- source/emulator/src/Graphics/Window.cpp | 10 +- source/emulator/src/Kernel/EventFlag.cpp | 24 +- source/emulator/src/Kernel/Memory.cpp | 25 +- source/emulator/src/Kernel/Pthread.cpp | 14 + source/emulator/src/Kyty.cpp | 4 +- source/emulator/src/Libs/LibAppContent.cpp | 10 +- source/emulator/src/Libs/LibAudio.cpp | 42 + .../emulator/src/Libs/LibGraphicsDriver.cpp | 1 + source/emulator/src/Libs/LibKernel.cpp | 7 + source/emulator/src/Libs/LibNet.cpp | 9 + source/emulator/src/Libs/LibPlayGo.cpp | 32 +- .../Loader/{Param.cpp => SystemContent.cpp} | 133 ++- source/emulator/src/Loader/VirtualMemory.cpp | 24 + source/emulator/src/Network.cpp | 379 +++++- 26 files changed, 1862 insertions(+), 108 deletions(-) delete mode 100644 source/emulator/include/Emulator/Loader/Param.h create mode 100644 source/emulator/include/Emulator/Loader/SystemContent.h rename source/emulator/src/Loader/{Param.cpp => SystemContent.cpp} (75%) diff --git a/appveyor.yml b/appveyor.yml index 4e08540..f65bbfd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 0.1.4.build-{build} +version: 0.1.5.build-{build} image: Visual Studio 2019 environment: matrix: diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 8b983b3..56f68f9 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.1.4) +project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.1.5) include(src_script.cmake) diff --git a/source/emulator/include/Emulator/Audio.h b/source/emulator/include/Emulator/Audio.h index cc01871..c4d5d29 100644 --- a/source/emulator/include/Emulator/Audio.h +++ b/source/emulator/include/Emulator/Audio.h @@ -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 diff --git a/source/emulator/include/Emulator/Graphics/Graphics.h b/source/emulator/include/Emulator/Graphics/Graphics.h index 30f5c59..54ae6b9 100644 --- a/source/emulator/include/Emulator/Graphics/Graphics.h +++ b/source/emulator/include/Emulator/Graphics/Graphics.h @@ -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, diff --git a/source/emulator/include/Emulator/Kernel/Pthread.h b/source/emulator/include/Emulator/Kernel/Pthread.h index d9db63f..45a683f 100644 --- a/source/emulator/include/Emulator/Kernel/Pthread.h +++ b/source/emulator/include/Emulator/Kernel/Pthread.h @@ -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); diff --git a/source/emulator/include/Emulator/Loader/Param.h b/source/emulator/include/Emulator/Loader/Param.h deleted file mode 100644 index ef509ad..0000000 --- a/source/emulator/include/Emulator/Loader/Param.h +++ /dev/null @@ -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_ */ diff --git a/source/emulator/include/Emulator/Loader/SystemContent.h b/source/emulator/include/Emulator/Loader/SystemContent.h new file mode 100644 index 0000000..c93f047 --- /dev/null +++ b/source/emulator/include/Emulator/Loader/SystemContent.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_ */ diff --git a/source/emulator/include/Emulator/Loader/VirtualMemory.h b/source/emulator/include/Emulator/Loader/VirtualMemory.h index 1cfb3c0..381a01f 100644 --- a/source/emulator/include/Emulator/Loader/VirtualMemory.h +++ b/source/emulator/include/Emulator/Loader/VirtualMemory.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); diff --git a/source/emulator/include/Emulator/Network.h b/source/emulator/include/Emulator/Network.h index 05982a8..e7054a0 100644 --- a/source/emulator/include/Emulator/Network.h +++ b/source/emulator/include/Emulator/Network.h @@ -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); diff --git a/source/emulator/src/Audio.cpp b/source/emulator/src/Audio.cpp index 911421e..86a4576 100644 --- a/source/emulator/src/Audio.cpp +++ b/source/emulator/src/Audio.cpp @@ -7,9 +7,12 @@ #include "Kyty/Core/Threads.h" #include "Emulator/Kernel/Pthread.h" +#include "Emulator/Kernel/Semaphore.h" #include "Emulator/Libs/Errno.h" #include "Emulator/Libs/Libs.h" +#include + #ifdef KYTY_EMU_ENABLED namespace Kyty::Libs::Audio { @@ -69,6 +72,7 @@ public: bool AudioOutValid(Id handle); bool AudioOutSetVolume(Id handle, uint32_t bitflag, const int* volume); uint32_t AudioOutOutputs(OutputParam* params, uint32_t num); + bool AudioOutGetStatus(Id handle, int* type, int* channels_num); Id AudioInOpen(uint32_t type, uint32_t samples_num, uint32_t freq, Format format); bool AudioInValid(Id handle); @@ -180,6 +184,23 @@ bool Audio::AudioOutValid(Id handle) return (handle.GetId() >= 0 && handle.GetId() < OUT_PORTS_MAX && m_out_ports[handle.GetId()].used); } +bool Audio::AudioOutGetStatus(Id handle, int* type, int* channels_num) +{ + Core::LockGuard lock(m_mutex); + + if (AudioOutValid(handle)) + { + auto& port = m_out_ports[handle.GetId()]; + + *type = port.type; + *channels_num = port.channels_num; + + return true; + } + + return false; +} + bool Audio::AudioOutSetVolume(Id handle, uint32_t bitflag, const int* volume) { Core::LockGuard lock(m_mutex); @@ -316,6 +337,17 @@ struct AudioOutOutputParam const void* ptr; }; +struct AudioOutPortState +{ + uint16_t output; + uint8_t channel; + uint8_t reserved1[1]; + int16_t volume; + uint16_t reroute_counter; + uint64_t flag; + uint64_t reserved2[2]; +}; + int KYTY_SYSV_ABI AudioOutInit() { PRINT_NAME(); @@ -334,7 +366,7 @@ int KYTY_SYSV_ABI AudioOutOpen(int user_id, int type, int index, uint32_t len, u printf("\t freq = %u\n", freq); EXIT_NOT_IMPLEMENTED(user_id != 255 && user_id != 1); - EXIT_NOT_IMPLEMENTED(type != 0 && type != 3 && type != 4); + EXIT_NOT_IMPLEMENTED(type != 0 && type != 1 && type != 3 && type != 4); EXIT_NOT_IMPLEMENTED(index != 0); Audio::Format format = Audio::Format::Unknown; @@ -380,6 +412,49 @@ int KYTY_SYSV_ABI AudioOutClose(int handle) return OK; } +int KYTY_SYSV_ABI AudioOutGetPortState(int handle, AudioOutPortState* state) +{ + PRINT_NAME(); + + int type = 0; + int channels_num = 0; + + if (!g_audio->AudioOutGetStatus(Audio::Id(handle), &type, &channels_num)) + { + return AUDIO_OUT_ERROR_INVALID_PORT; + } + + EXIT_NOT_IMPLEMENTED(state == nullptr); + + state->reroute_counter = 0; + state->volume = 127; + + switch (type) + { + case 0: + case 1: + case 2: + state->output = 1; + state->channel = (channels_num > 2 ? 2 : channels_num); + break; + case 3: + case 127: + state->output = 0; + state->channel = 0; + break; + case 4: + state->output = 4; + state->channel = 1; + break; + default: EXIT("unknown port type: %d\n", type); + } + + printf("\t output = %" PRIu16 "\n", state->output); + printf("\t channel = %" PRIu8 "\n", state->channel); + + return OK; +} + int KYTY_SYSV_ABI AudioOutSetVolume(int handle, uint32_t flag, int* vol) { PRINT_NAME(); @@ -968,6 +1043,980 @@ int KYTY_SYSV_ABI AvPlayerClose(AvPlayerInternal* h) } // namespace AvPlayer +namespace Audio3d { + +LIB_NAME("Audio3d", "Audio3d"); + +namespace Semaphore = LibKernel::Semaphore; + +struct Audio3dOpenParameters +{ + size_t size = 0x20; + uint32_t granularity = 256; + uint32_t rate = 0; + uint32_t max_objects = 512; + uint32_t queue_depth = 2; + uint32_t buffer_mode = 2; + uint32_t pad = 0; + // uint32_t num_beds; +}; + +struct Audio3dData +{ + enum class State + { + Empty, + Ready, + Play + }; + + std::atomic state = State::Empty; +}; + +struct Audio3dInternal +{ + Audio3dData* data = nullptr; + Core::Mutex* data_mutex = nullptr; + uint64_t data_delay = 0; + Semaphore::KernelSema playback_sema = nullptr; + Audio3dOpenParameters params = {}; + int user_id = 0; + float late_reverb_level = 0.0f; + float downmix_spread_radius = 2.0f; + int downmix_spread_height_aware = 0; + uint32_t data_index = 0; + bool used = false; + std::atomic_bool playback_finished = false; +}; + +constexpr uint32_t MAX_PORTS = 4; + +static Audio3dInternal g_ports[MAX_PORTS] = {}; + +static void playback_simulate(void* arg) +{ + auto* port = static_cast(arg); + EXIT_IF(port == nullptr); + EXIT_IF(port->data_mutex == nullptr); + EXIT_IF(port->data == nullptr); + + for (;;) + { + int result = Semaphore::KernelWaitSema(port->playback_sema, 1, nullptr); + + if (result != OK) + { + break; + } + + Audio3dData* play_data = nullptr; + + port->data_mutex->Lock(); + { + for (uint32_t i = 0; i < port->params.queue_depth; i++) + { + uint32_t index = (port->data_index + i) % port->params.queue_depth; + + if (port->data[index].state == Audio3dData::State::Play) + { + play_data = &port->data[index]; + break; + } + } + } + port->data_mutex->Unlock(); + + EXIT_IF(play_data == nullptr); + + // TODO(): Audio output is not yet implemented, so simulate audio delay + Core::Thread::SleepMicro(port->data_delay); + play_data->state = Audio3dData::State::Empty; + } + + port->playback_finished = true; +} + +int KYTY_SYSV_ABI Audio3dInitialize(int64_t reserved) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(reserved != 0); + + return OK; +} + +void KYTY_SYSV_ABI Audio3dGetDefaultOpenParameters(Audio3dOpenParameters* p) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(sizeof(Audio3dOpenParameters) != 0x20); + + *p = Audio3dOpenParameters(); +} + +int KYTY_SYSV_ABI Audio3dPortOpen(int user_id, const Audio3dOpenParameters* parameters, uint32_t* id) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(parameters == nullptr); + EXIT_NOT_IMPLEMENTED(id == nullptr); + EXIT_NOT_IMPLEMENTED(parameters->size != 0x20); + + printf("\t user_id = %d\n", user_id); + printf("\t granularity = %u\n", parameters->granularity); + printf("\t rate = %u\n", parameters->rate); + printf("\t max_objects = %u\n", parameters->max_objects); + printf("\t queue_depth = %u\n", parameters->queue_depth); + printf("\t buffer_mode = %u\n", parameters->buffer_mode); + + EXIT_NOT_IMPLEMENTED(parameters->buffer_mode != 2); + EXIT_NOT_IMPLEMENTED(user_id != 255 && user_id != 1); + + uint32_t port = 0; + for (; port < MAX_PORTS; port++) + { + if (!g_ports[port].used) + { + break; + } + } + + EXIT_NOT_IMPLEMENTED(port >= MAX_PORTS); + + g_ports[port].user_id = user_id; + g_ports[port].params = *parameters; + g_ports[port].used = true; + + EXIT_IF(g_ports[port].data != nullptr); + EXIT_IF(g_ports[port].data_mutex != nullptr); + EXIT_IF(g_ports[port].playback_sema != nullptr); + + g_ports[port].data = new Audio3dData[parameters->queue_depth]; + g_ports[port].data_index = 0; + g_ports[port].data_mutex = new Core::Mutex; + g_ports[port].data_delay = (1000000 * static_cast(parameters->granularity)) / 48000; + + for (uint32_t d = 0; d < parameters->queue_depth; d++) + { + g_ports[port].data[d].state = Audio3dData::State::Empty; + } + + int result = Semaphore::KernelCreateSema(&g_ports[port].playback_sema, "audio3d_play", 0x01, 0, + static_cast(parameters->queue_depth), nullptr); + EXIT_NOT_IMPLEMENTED(result != OK); + + g_ports[port].playback_finished = false; + Core::Thread playback_thread(playback_simulate, &g_ports[port]); + playback_thread.Detach(); + + *id = port; + + return OK; +} + +int KYTY_SYSV_ABI Audio3dPortSetAttribute(uint32_t port_id, uint32_t attribute_id, const void* attribute, size_t attribute_size) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(port_id >= MAX_PORTS); + EXIT_NOT_IMPLEMENTED(!g_ports[port_id].used); + EXIT_NOT_IMPLEMENTED(attribute == nullptr); + + printf("\t attribute_id = 0x%" PRIx32 "\n", attribute_id); + + switch (attribute_id) + { + case 0x10001: + EXIT_NOT_IMPLEMENTED(attribute_size != 4); + g_ports[port_id].late_reverb_level = *static_cast(attribute); + printf("\t late_reverb_level = %f\n", g_ports[port_id].late_reverb_level); + break; + case 0x10002: + EXIT_NOT_IMPLEMENTED(attribute_size != 4); + g_ports[port_id].downmix_spread_radius = *static_cast(attribute); + printf("\t downmix_spread_radius = %f\n", g_ports[port_id].downmix_spread_radius); + break; + case 0x10003: + EXIT_NOT_IMPLEMENTED(attribute_size != 4); + g_ports[port_id].downmix_spread_height_aware = *static_cast(attribute); + printf("\t downmix_spread_height_aware = %d\n", g_ports[port_id].downmix_spread_height_aware); + break; + default: EXIT("unknown attribute: 0x%" PRIx32 "\n", attribute_id); + } + + return OK; +} + +int KYTY_SYSV_ABI Audio3dPortGetQueueLevel(uint32_t port_id, uint32_t* queue_level, uint32_t* queue_available) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(port_id >= MAX_PORTS); + EXIT_NOT_IMPLEMENTED(!g_ports[port_id].used); + EXIT_NOT_IMPLEMENTED(queue_level == nullptr && queue_available == nullptr); + + auto* port = &g_ports[port_id]; + + uint32_t empty_num = 0; + + port->data_mutex->Lock(); + { + for (uint32_t i = 0; i < port->params.queue_depth; i++) + { + uint32_t index = (port->data_index + i) % port->params.queue_depth; + + if (port->data[index].state == Audio3dData::State::Empty) + { + empty_num++; + } else + { + break; + } + } + } + port->data_mutex->Unlock(); + + EXIT_IF(empty_num > port->params.queue_depth); + + printf("\t queue_available = %u\n", empty_num); + + if (queue_level != nullptr) + { + *queue_level = port->params.queue_depth - empty_num; + } + if (queue_available != nullptr) + { + *queue_available = empty_num; + } + + return OK; +} + +int KYTY_SYSV_ABI Audio3dPortAdvance(uint32_t port_id) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(port_id >= MAX_PORTS); + EXIT_NOT_IMPLEMENTED(!g_ports[port_id].used); + + auto* port = &g_ports[port_id]; + + port->data_mutex->Lock(); + { + uint32_t current_index = port->data_index; + uint32_t next_index = (current_index + 1) % port->params.queue_depth; + + if (port->data[current_index].state == Audio3dData::State::Empty) + { + port->data[current_index].state = Audio3dData::State::Ready; + } + + EXIT_NOT_IMPLEMENTED(port->data[current_index].state != Audio3dData::State::Ready); + + port->data_index = next_index; + + printf("\t %u -> %u\n", current_index, next_index); + } + port->data_mutex->Unlock(); + + return OK; +} + +int KYTY_SYSV_ABI Audio3dPortPush(uint32_t port_id, uint32_t blocking) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(port_id >= MAX_PORTS); + EXIT_NOT_IMPLEMENTED(!g_ports[port_id].used); + + auto* port = &g_ports[port_id]; + + EXIT_NOT_IMPLEMENTED(blocking != 1); + + printf("\t blocking = %u\n", blocking); + + int data_num = 0; + Audio3dData* first_data = nullptr; + + port->data_mutex->Lock(); + { + first_data = port->data + port->data_index; + + for (uint32_t i = 0; i < port->params.queue_depth; i++) + { + uint32_t index = (port->data_index + i) % port->params.queue_depth; + + if (port->data[index].state == Audio3dData::State::Ready) + { + port->data[index].state = Audio3dData::State::Play; + data_num++; + } + } + } + port->data_mutex->Unlock(); + + printf("\t push num = %d\n", data_num); + + if (data_num > 0) + { + Semaphore::KernelSignalSema(port->playback_sema, data_num); + + if (blocking == 1) + { + auto wait_time = port->data_delay / 8; + while (first_data->state != Audio3dData::State::Empty) + { + Core::Thread::SleepMicro(wait_time); + } + } + } + + return OK; +} + +} // namespace Audio3d + +namespace Ngs2 { + +LIB_NAME("Ngs2", "Ngs2"); + +struct Ngs2SystemOption +{ + size_t size = 0; + char name[16] = {}; + uint32_t flags = 0; + uint32_t max_grain_samples = 0; + uint32_t num_grain_samples = 0; + uint32_t sample_rate = 0; + uint32_t reserved[6] = {}; +}; + +struct Ngs2RackOption +{ + size_t size = 0; + char name[16] = {}; + uint32_t flags = 0; + uint32_t max_grain_samples = 0; + uint32_t max_voices = 0; + uint32_t max_input_delay_blocks = 0; + uint32_t max_matrices = 0; + uint32_t max_ports = 0; + uint32_t reserved[20] = {}; +}; + +struct Ngs2MasteringRackOption +{ + Ngs2RackOption rack_option; + uint32_t max_channels = 0; + uint32_t num_peak_meter_blocks = 0; +}; + +struct Ngs2SubmixerRackOption +{ + Ngs2RackOption rack_option; + uint32_t max_channels = 0; + uint32_t max_envelope_points = 0; + uint32_t max_filters = 0; + uint32_t max_inputs = 0; + uint32_t num_peak_meter_blocks = 0; +}; + +struct Ngs2SamplerRackOption +{ + Ngs2RackOption rack_option; + uint32_t max_channel_works = 0; + uint32_t max_codec_caches = 0; + uint32_t max_waveform_blocks = 0; + uint32_t max_envelope_points = 0; + uint32_t max_filters = 0; + uint32_t max_atrac9_decoders = 0; + uint32_t max_atrac9_channel_works = 0; + uint32_t max_ajm_atrac9_decoders = 0; + uint32_t num_peak_meter_blocks = 0; +}; + +struct Ngs2ReverbRackOption +{ + Ngs2RackOption rack_option; + uint32_t max_channels = 0; + uint32_t reverb_size = 0; +}; + +struct Ngs2CustomModuleOption +{ + uint32_t size = 0; +}; + +struct Ngs2CustomRackModuleInfo +{ + const Ngs2CustomModuleOption* option = nullptr; + uint32_t module_id = 0; + uint32_t source_buffer_id = 0; + uint32_t extra_buffer_id = 0; + uint32_t dest_buffer_id = 0; + uint32_t state_offset = 0; + uint32_t state_size = 0; + uint32_t reserved = 0; + uint32_t reserved2 = 0; +}; + +struct Ngs2CustomRackPortInfo +{ + uint32_t source_buffer_id = 0; + uint32_t reserved = 0; +}; + +struct Ngs2CustomRackOption +{ + Ngs2RackOption rack_option; + uint32_t state_size = 0; + uint32_t num_buffers = 0; + uint32_t num_modules = 0; + uint32_t reserved = 0; + Ngs2CustomRackModuleInfo module[24]; + Ngs2CustomRackPortInfo port[16]; +}; + +struct Ngs2CustomSubmixerRackOption +{ + Ngs2CustomRackOption custom_rack_option; + uint32_t max_channels = 0; + uint32_t max_inputs = 0; +}; + +union Ngs2RackOptionUnion +{ + Ngs2RackOption common; + Ngs2SamplerRackOption sampler; + Ngs2MasteringRackOption mastering; + Ngs2SubmixerRackOption submixer; + Ngs2ReverbRackOption reverb; + Ngs2CustomSubmixerRackOption custom_submixer; +}; + +struct Ngs2ContextBufferInfo +{ + void* host_buffer = nullptr; + size_t host_buffer_size = 0; + uintptr_t reserved[5] = {}; + uintptr_t user_data = 0; +}; + +using Ngs2BufferAllocHandler = int32_t KYTY_SYSV_ABI (*)(Ngs2ContextBufferInfo*); +using Ngs2BufferFreeHandler = int32_t KYTY_SYSV_ABI (*)(Ngs2ContextBufferInfo*); + +struct Ngs2BufferAllocator +{ + Ngs2BufferAllocHandler alloc_handler = nullptr; + Ngs2BufferFreeHandler free_handler = nullptr; + uintptr_t user_data = 0; +}; + +struct Ngs2Internal +{ + Ngs2SystemOption option; + Ngs2BufferAllocator allocator; + Ngs2Internal* next = nullptr; + Core::Mutex mutex; +}; + +enum class Ngs2RackType +{ + Sampler, + Submixer, + Mastering, + Reverb, + CustomSubmixer, +}; + +struct Ngs2RackInternal +{ + Ngs2Internal* ngs = nullptr; + Ngs2RackInternal* next = nullptr; + Ngs2RackType type = Ngs2RackType::Sampler; + Ngs2RackOptionUnion option; + Ngs2BufferAllocator allocator; +}; + +enum class Ngs2VoicePlayState +{ + Empty, + Playing, + Paused, + Stopped +}; + +enum class Ngs2VoicePlayEvent +{ + None, + Play, + Pause, + Resume, + Stop, + StopImm, + Kill +}; + +struct Ngs2VoiceInternal +{ + Ngs2VoicePlayEvent event = Ngs2VoicePlayEvent::None; + Ngs2VoicePlayState state = Ngs2VoicePlayState::Empty; + Ngs2RackInternal* rack = nullptr; +}; + +struct Ngs2VoiceParamHeader +{ + uint16_t size; + int16_t next; + uint32_t id; +}; + +struct Ngs2VoiceEventParam +{ + Ngs2VoiceParamHeader header; + uint32_t event_id; +}; + +struct Ngs2VoicePatchParam +{ + Ngs2VoiceParamHeader header; + uint32_t port; + uint32_t dest_input_id; + uintptr_t dest_handle; +}; + +struct Ngs2VoicePortMatrixParam +{ + Ngs2VoiceParamHeader header; + uint32_t port; + int32_t matrix_id; +}; + +struct Ngs2VoiceState +{ + uint32_t state_flags; +}; + +struct Ngs2SamplerVoiceState +{ + Ngs2VoiceState voice_state; + float envelope_height; + float peak_height; + uint32_t reserved; + uint64_t num_decoded_samples; + uint64_t decoded_data_size; + uint64_t user_data; + const void* waveform_data; +}; + +static Ngs2Internal* g_ngs_list = nullptr; +static Ngs2RackInternal* g_racks_list = nullptr; + +int KYTY_SYSV_ABI Ngs2RackQueryBufferSize(uint32_t rack_id, const Ngs2RackOption* option, Ngs2ContextBufferInfo* buffer_info) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(option == nullptr); + EXIT_NOT_IMPLEMENTED(buffer_info == nullptr); + + printf("\t rack_id = 0x%" PRIx32 "\n", rack_id); + printf("\t max_voices = %u\n", option->max_voices); + + buffer_info->host_buffer_size = sizeof(Ngs2RackInternal) + sizeof(Ngs2VoiceInternal) * option->max_voices; + + return OK; +} + +int KYTY_SYSV_ABI Ngs2SystemCreateWithAllocator(const Ngs2SystemOption* option, const Ngs2BufferAllocator* allocator, uintptr_t* handle) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(option == nullptr); + EXIT_NOT_IMPLEMENTED(allocator == nullptr); + EXIT_NOT_IMPLEMENTED(handle == nullptr); + EXIT_NOT_IMPLEMENTED(allocator->alloc_handler == nullptr); + EXIT_NOT_IMPLEMENTED(allocator->free_handler == nullptr); + + EXIT_NOT_IMPLEMENTED(option->size != sizeof(Ngs2SystemOption)); + + printf("\t name = %.16s\n", option->name); + printf("\t flags = %u\n", option->flags); + printf("\t max_grain_samples = %u\n", option->max_grain_samples); + printf("\t num_grain_samples = %u\n", option->num_grain_samples); + printf("\t sample_rate = %u\n", option->sample_rate); + printf("\t alloc_handler = 0x%016" PRIx64 "\n", reinterpret_cast(allocator->alloc_handler)); + printf("\t free_handler = 0x%016" PRIx64 "\n", reinterpret_cast(allocator->free_handler)); + printf("\t user_data = 0x%016" PRIx64 "\n", reinterpret_cast(allocator->user_data)); + + Ngs2ContextBufferInfo buf {}; + buf.host_buffer = nullptr; + buf.host_buffer_size = sizeof(Ngs2Internal); + buf.user_data = allocator->user_data; + + int result = allocator->alloc_handler(&buf); + + EXIT_NOT_IMPLEMENTED(result != OK); + EXIT_NOT_IMPLEMENTED(buf.host_buffer == nullptr); + + auto* ngs = new (buf.host_buffer) Ngs2Internal; + + ngs->option = *option; + ngs->allocator = *allocator; + + ngs->next = g_ngs_list; + g_ngs_list = ngs; + + *handle = reinterpret_cast(ngs); + + return OK; +} + +int KYTY_SYSV_ABI Ngs2RackCreate(uintptr_t system_handle, uint32_t rack_id, const Ngs2RackOption* option, + const Ngs2ContextBufferInfo* buffer_info, uintptr_t* handle) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(option == nullptr); + EXIT_NOT_IMPLEMENTED(buffer_info == nullptr); + EXIT_NOT_IMPLEMENTED(handle == nullptr); + EXIT_NOT_IMPLEMENTED(buffer_info->host_buffer == nullptr); + EXIT_NOT_IMPLEMENTED(buffer_info->host_buffer_size == 0); + EXIT_NOT_IMPLEMENTED(system_handle == 0); + + EXIT_NOT_IMPLEMENTED(option->size < sizeof(Ngs2RackOption)); + + printf("\t rack_id = 0x%" PRIx32 "\n", rack_id); + printf("\t name = %.16s\n", option->name); + printf("\t flags = %u\n", option->flags); + printf("\t max_grain_samples = %u\n", option->max_grain_samples); + printf("\t max_voices = %u\n", option->max_voices); + printf("\t max_input_delay_blocks = %u\n", option->max_input_delay_blocks); + printf("\t max_matrices = %u\n", option->max_matrices); + printf("\t max_ports = %u\n", option->max_ports); + printf("\t host_buffer = 0x%016" PRIx64 "\n", reinterpret_cast(buffer_info->host_buffer)); + printf("\t host_buffer_size = 0x%016" PRIx64 "\n", reinterpret_cast(buffer_info->host_buffer_size)); + + auto* ngs = reinterpret_cast(system_handle); + auto* rack = static_cast(buffer_info->host_buffer); + auto* voices = reinterpret_cast(rack + 1); + + Core::LockGuard lock(ngs->mutex); + + switch (rack_id) + { + case 0x1000: + EXIT_NOT_IMPLEMENTED(option->size != sizeof(Ngs2SamplerRackOption)); + rack->option.sampler = *reinterpret_cast(option); + rack->type = Ngs2RackType::Sampler; + break; + case 0x2000: + EXIT_NOT_IMPLEMENTED(option->size != sizeof(Ngs2SubmixerRackOption)); + rack->option.submixer = *reinterpret_cast(option); + rack->type = Ngs2RackType::Submixer; + break; + case 0x2001: + EXIT_NOT_IMPLEMENTED(option->size != sizeof(Ngs2ReverbRackOption)); + rack->option.reverb = *reinterpret_cast(option); + rack->type = Ngs2RackType::Reverb; + break; + case 0x3000: + EXIT_NOT_IMPLEMENTED(option->size != sizeof(Ngs2MasteringRackOption)); + rack->option.mastering = *reinterpret_cast(option); + rack->type = Ngs2RackType::Mastering; + break; + case 0x4002: + EXIT_NOT_IMPLEMENTED(option->size != sizeof(Ngs2CustomSubmixerRackOption)); + rack->option.custom_submixer = *reinterpret_cast(option); + rack->type = Ngs2RackType::CustomSubmixer; + break; + default: EXIT("unknown rack_id: 0x%" PRIx32 "\n", rack_id); + } + + printf("\t type = %s\n", Core::EnumName(rack->type).C_Str()); + + rack->allocator = Ngs2BufferAllocator(); + rack->ngs = ngs; + + rack->next = g_racks_list; + g_racks_list = rack; + + for (uint32_t i = 0; i < option->max_voices; i++) + { + voices[i].rack = rack; + voices[i].event = Ngs2VoicePlayEvent::None; + voices[i].state = Ngs2VoicePlayState::Empty; + } + + *handle = reinterpret_cast(rack); + + return OK; +} + +int KYTY_SYSV_ABI Ngs2RackCreateWithAllocator(uintptr_t system_handle, uint32_t rack_id, const Ngs2RackOption* option, + const Ngs2BufferAllocator* allocator, uintptr_t* handle) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(option == nullptr); + EXIT_NOT_IMPLEMENTED(allocator == nullptr); + EXIT_NOT_IMPLEMENTED(handle == nullptr); + EXIT_NOT_IMPLEMENTED(allocator->alloc_handler == nullptr); + EXIT_NOT_IMPLEMENTED(allocator->free_handler == nullptr); + EXIT_NOT_IMPLEMENTED(system_handle == 0); + + EXIT_NOT_IMPLEMENTED(option->size < sizeof(Ngs2RackOption)); + + printf("\t rack_id = 0x%" PRIx32 "\n", rack_id); + printf("\t name = %.16s\n", option->name); + printf("\t flags = %u\n", option->flags); + printf("\t max_grain_samples = %u\n", option->max_grain_samples); + printf("\t max_voices = %u\n", option->max_voices); + printf("\t max_input_delay_blocks = %u\n", option->max_input_delay_blocks); + printf("\t max_matrices = %u\n", option->max_matrices); + printf("\t max_ports = %u\n", option->max_ports); + printf("\t alloc_handler = 0x%016" PRIx64 "\n", reinterpret_cast(allocator->alloc_handler)); + printf("\t free_handler = 0x%016" PRIx64 "\n", reinterpret_cast(allocator->free_handler)); + printf("\t user_data = 0x%016" PRIx64 "\n", reinterpret_cast(allocator->user_data)); + + Ngs2ContextBufferInfo buf {}; + buf.host_buffer = nullptr; + buf.host_buffer_size = 0; + buf.user_data = allocator->user_data; + + Ngs2RackQueryBufferSize(rack_id, option, &buf); + + EXIT_NOT_IMPLEMENTED(buf.host_buffer_size == 0); + + int result = allocator->alloc_handler(&buf); + + EXIT_NOT_IMPLEMENTED(result != OK); + EXIT_NOT_IMPLEMENTED(buf.host_buffer == nullptr); + + result = Ngs2RackCreate(system_handle, rack_id, option, &buf, handle); + + if (result == OK) + { + auto* rack = static_cast(buf.host_buffer); + rack->allocator = *allocator; + } + + return result; +} + +int KYTY_SYSV_ABI Ngs2SystemRender(uintptr_t system_handle, const Ngs2RenderBufferInfo* buffer_info, uint32_t num_buffer_info) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(buffer_info == nullptr); + EXIT_NOT_IMPLEMENTED(system_handle == 0); + EXIT_NOT_IMPLEMENTED(num_buffer_info == 0); + + auto* ngs = reinterpret_cast(system_handle); + + Core::LockGuard lock(ngs->mutex); + + for (auto* rack = g_racks_list; rack != nullptr; rack = rack->next) + { + if (rack->ngs == ngs) + { + auto* voices = reinterpret_cast(rack + 1); + + for (uint32_t i = 0; i < rack->option.common.max_voices; i++) + { + auto& voice = voices[i]; + switch (voice.event) + { + case Ngs2VoicePlayEvent::None: + if (voice.state == Ngs2VoicePlayState::Playing || voice.state == Ngs2VoicePlayState::Stopped) + { + voice.state = Ngs2VoicePlayState::Empty; + } + break; + case Ngs2VoicePlayEvent::Play: + if (voice.state == Ngs2VoicePlayState::Empty) + { + voice.state = Ngs2VoicePlayState::Playing; + } + break; + case Ngs2VoicePlayEvent::Pause: + if (voice.state == Ngs2VoicePlayState::Playing) + { + voice.state = Ngs2VoicePlayState::Paused; + } + break; + case Ngs2VoicePlayEvent::Resume: + if (voice.state == Ngs2VoicePlayState::Paused) + { + voice.state = Ngs2VoicePlayState::Playing; + } + break; + case Ngs2VoicePlayEvent::Stop: + if (voice.state == Ngs2VoicePlayState::Playing) + { + voice.state = Ngs2VoicePlayState::Stopped; + } + break; + case Ngs2VoicePlayEvent::StopImm: + case Ngs2VoicePlayEvent::Kill: voice.state = Ngs2VoicePlayState::Empty; break; + } + voice.event = Ngs2VoicePlayEvent::None; + } + } + } + + return OK; +} + +int KYTY_SYSV_ABI Ngs2RackGetVoiceHandle(uintptr_t rack_handle, uint32_t voice_id, uintptr_t* handle) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(handle == nullptr); + EXIT_NOT_IMPLEMENTED(rack_handle == 0); + + printf("\t voice_id = %u\n", voice_id); + + auto* rack = reinterpret_cast(rack_handle); + auto* voices = reinterpret_cast(rack_handle + sizeof(Ngs2RackInternal)); + + EXIT_NOT_IMPLEMENTED(voice_id >= rack->option.common.max_voices); + + EXIT_IF(voices[voice_id].rack != rack); + + *handle = reinterpret_cast(voices + voice_id); + + return OK; +} + +// NOLINTNEXTLINE(readability-function-cognitive-complexity) +int KYTY_SYSV_ABI Ngs2VoiceControl(uintptr_t voice_handle, const Ngs2VoiceParamHeader* param_list) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(param_list == nullptr); + EXIT_NOT_IMPLEMENTED(voice_handle == 0); + + auto* voice = reinterpret_cast(voice_handle); + + Core::LockGuard lock(voice->rack->ngs->mutex); + + const auto* param = param_list; + + for (;;) + { + printf("\t id = 0x%08" PRIx32 "\n", param->id); + printf("\t size = %" PRIu16 "\n", param->size); + printf("\t next = %" PRId16 "\n", param->next); + + auto rack_id = param->id >> 16u; + + EXIT_NOT_IMPLEMENTED(((param->id >> 15u) & 0x1u) != 0); + + switch (rack_id) + { + case 0x0000: + { + auto cid = param->id & 0x7fffu; + switch (cid) + { + case 0x0002: + { + EXIT_NOT_IMPLEMENTED(param->size != sizeof(Ngs2VoicePortMatrixParam)); + const auto* pm = reinterpret_cast(param); + printf("\t port = %u\n", pm->port); + printf("\t matrix_id = %d\n", pm->matrix_id); + break; + } + case 0x0005: + { + EXIT_NOT_IMPLEMENTED(param->size != sizeof(Ngs2VoicePatchParam)); + const auto* patch = reinterpret_cast(param); + printf("\t connect->port = %u\n", patch->port); + printf("\t connect->dest_input_id = %u\n", patch->dest_input_id); + printf("\t connect->dest_handle = 0x%016" PRIx64 "\n", patch->dest_handle); + break; + } + case 0x0006: + { + EXIT_NOT_IMPLEMENTED(param->size != sizeof(Ngs2VoiceEventParam)); + const auto* event = reinterpret_cast(param); + switch (event->event_id) + { + case 0: voice->event = Ngs2VoicePlayEvent::Play; break; + case 1: voice->event = Ngs2VoicePlayEvent::Stop; break; + case 2: voice->event = Ngs2VoicePlayEvent::StopImm; break; + case 3: voice->event = Ngs2VoicePlayEvent::Kill; break; + case 4: voice->event = Ngs2VoicePlayEvent::Pause; break; + case 5: voice->event = Ngs2VoicePlayEvent::Resume; break; + default: EXIT("unknown event_id: 0x%08" PRIx32 "\n", event->event_id); + } + printf("\t event = %u\n", event->event_id); + break; + } + default: EXIT("unknown id: 0x%04" PRIx32 "\n", cid); + } + break; + } + case 0x1000: EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::Sampler); break; + case 0x2000: EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::Submixer); break; + case 0x2001: EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::Reverb); break; + case 0x3000: EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::Mastering); break; + case 0x4000: EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::CustomSubmixer); break; + case 0x4002: EXIT_NOT_IMPLEMENTED(voice->rack->type != Ngs2RackType::CustomSubmixer); break; + default: EXIT("unknown rack_id: 0x%" PRIx32 "\n", rack_id); + } + + if (param->next == 0) + { + break; + } + param = reinterpret_cast(reinterpret_cast(param) + param->next); + } + + return OK; +} + +int KYTY_SYSV_ABI Ngs2VoiceGetState(uintptr_t voice_handle, Ngs2VoiceState* state, size_t state_size) +{ + PRINT_NAME(); + + EXIT_NOT_IMPLEMENTED(state == nullptr); + EXIT_NOT_IMPLEMENTED(voice_handle == 0); + + auto* voice = reinterpret_cast(voice_handle); + + Core::LockGuard lock(voice->rack->ngs->mutex); + + switch (voice->rack->type) + { + case Ngs2RackType::Sampler: + { + EXIT_NOT_IMPLEMENTED(state_size != sizeof(Ngs2SamplerVoiceState)); + auto* sampler = reinterpret_cast(state); + switch (voice->state) + { + case Ngs2VoicePlayState::Empty: sampler->voice_state.state_flags = 0; break; + case Ngs2VoicePlayState::Playing: sampler->voice_state.state_flags = 0x3; break; + case Ngs2VoicePlayState::Paused: sampler->voice_state.state_flags = 0x5; break; + case Ngs2VoicePlayState::Stopped: sampler->voice_state.state_flags = 0xb; break; + } + sampler->envelope_height = 1.0f; + sampler->peak_height = 0.0f; + sampler->reserved = 0; + sampler->num_decoded_samples = 0; + sampler->user_data = 0; + sampler->waveform_data = nullptr; + printf("\t state_flags = %u\n", sampler->voice_state.state_flags); + break; + } + default: EXIT("unknown type: %s\n", Core::EnumName(voice->rack->type).C_Str()); + } + + return OK; +} + +} // namespace Ngs2 + } // namespace Kyty::Libs::Audio #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Graphics/Graphics.cpp b/source/emulator/src/Graphics/Graphics.cpp index eb679f8..19d6c88 100644 --- a/source/emulator/src/Graphics/Graphics.cpp +++ b/source/emulator/src/Graphics/Graphics.cpp @@ -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 @@ -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(addr); +} + int KYTY_SYSV_ABI GraphicsRegisterOwner(uint32_t* owner_handle, const char* name) { PRINT_NAME(); diff --git a/source/emulator/src/Graphics/GraphicsRun.cpp b/source/emulator/src/Graphics/GraphicsRun.cpp index fdaf7bc..20abc56 100644 --- a/source/emulator/src/Graphics/GraphicsRun.cpp +++ b/source/emulator/src/Graphics/GraphicsRun.cpp @@ -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(); diff --git a/source/emulator/src/Graphics/Window.cpp b/source/emulator/src/Graphics/Window.cpp index 506eacf..6c96b41 100644 --- a/source/emulator/src/Graphics/Window.cpp +++ b/source/emulator/src/Graphics/Window.cpp @@ -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 : ""), diff --git a/source/emulator/src/Kernel/EventFlag.cpp b/source/emulator/src/Kernel/EventFlag.cpp index 41b6e96..afbe944 100644 --- a/source/emulator/src/Kernel/EventFlag.cpp +++ b/source/emulator/src/Kernel/EventFlag.cpp @@ -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); diff --git a/source/emulator/src/Kernel/Memory.cpp b/source/emulator/src/Kernel/Memory.cpp index e70f4a9..66cf573 100644 --- a/source/emulator/src/Kernel/Memory.cpp +++ b/source/emulator/src/Kernel/Memory.cpp @@ -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(*addr); - auto out_addr = VirtualMemory::AllocAligned(in_addr, len, mode, alignment); - *addr = reinterpret_cast(out_addr); + auto in_addr = reinterpret_cast(*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(out_addr); printf("\t in_addr = 0x%016" PRIx64 "\n", in_addr); printf("\t out_addr = 0x%016" PRIx64 "\n", out_addr); diff --git a/source/emulator/src/Kernel/Pthread.cpp b/source/emulator/src/Kernel/Pthread.cpp index 33f3e06..c56f227 100644 --- a/source/emulator/src/Kernel/Pthread.cpp +++ b/source/emulator/src/Kernel/Pthread.cpp @@ -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(); diff --git a/source/emulator/src/Kyty.cpp b/source/emulator/src/Kyty.cpp index f4d3160..0af7831 100644 --- a/source/emulator/src/Kyty.cpp +++ b/source/emulator/src/Kyty.cpp @@ -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; diff --git a/source/emulator/src/Libs/LibAppContent.cpp b/source/emulator/src/Libs/LibAppContent.cpp index 93183dd..784aae6 100644 --- a/source/emulator/src/Libs/LibAppContent.cpp +++ b/source/emulator/src/Libs/LibAppContent.cpp @@ -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); } diff --git a/source/emulator/src/Libs/LibAudio.cpp b/source/emulator/src/Libs/LibAudio.cpp index f95b6fc..a83bfce 100644 --- a/source/emulator/src/Libs/LibAudio.cpp +++ b/source/emulator/src/Libs/LibAudio.cpp @@ -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 diff --git a/source/emulator/src/Libs/LibGraphicsDriver.cpp b/source/emulator/src/Libs/LibGraphicsDriver.cpp index e3620ea..7fded80 100644 --- a/source/emulator/src/Libs/LibGraphicsDriver.cpp +++ b/source/emulator/src/Libs/LibGraphicsDriver.cpp @@ -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 diff --git a/source/emulator/src/Libs/LibKernel.cpp b/source/emulator/src/Libs/LibKernel.cpp index 82c5762..5ae1f90 100644 --- a/source/emulator/src/Libs/LibKernel.cpp +++ b/source/emulator/src/Libs/LibKernel.cpp @@ -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); diff --git a/source/emulator/src/Libs/LibNet.cpp b/source/emulator/src/Libs/LibNet.cpp index 1b30b47..511551c 100644 --- a/source/emulator/src/Libs/LibNet.cpp +++ b/source/emulator/src/Libs/LibNet.cpp @@ -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); diff --git a/source/emulator/src/Libs/LibPlayGo.cpp b/source/emulator/src/Libs/LibPlayGo.cpp index ea61ce8..7dd3fb4 100644 --- a/source/emulator/src/Libs/LibPlayGo.cpp +++ b/source/emulator/src/Libs/LibPlayGo.cpp @@ -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); } diff --git a/source/emulator/src/Loader/Param.cpp b/source/emulator/src/Loader/SystemContent.cpp similarity index 75% rename from source/emulator/src/Loader/Param.cpp rename to source/emulator/src/Loader/SystemContent.cpp index f691ad3..56a1fce 100644 --- a/source/emulator/src/Loader/Param.cpp +++ b/source/emulator/src/Loader/SystemContent.cpp @@ -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::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::Instance(); return sc->icon; } +bool SystemContentGetChunksNum(uint32_t* num) +{ + if (num == nullptr) + { + return false; + } + + auto* sc = Core::Singleton::Instance(); + + return sc->playgo.GetChunksNum(num); +} + } // namespace Kyty::Loader #endif // KYTY_EMU_ENABLED diff --git a/source/emulator/src/Loader/VirtualMemory.cpp b/source/emulator/src/Loader/VirtualMemory.cpp index caa9a6d..d6c42b7 100644 --- a/source/emulator/src/Loader/VirtualMemory.cpp +++ b/source/emulator/src/Loader/VirtualMemory.cpp @@ -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(VirtualAlloc(reinterpret_cast(static_cast(address)), size, + static_cast(MEM_COMMIT) | static_cast(MEM_RESERVE), + get_protection_flag(mode))); + if (ptr == 0) + { + auto err = static_cast(GetLastError()); + + printf("VirtualAlloc() failed: 0x%08" PRIx32 "\n", err); + + return false; + } + + if (ptr != address) + { + printf("VirtualAlloc() failed: wrong address\n"); + VirtualFree(reinterpret_cast(ptr), 0, MEM_RELEASE); + return false; + } + + return true; +} + bool Free(uint64_t address) { if (VirtualFree(reinterpret_cast(static_cast(address)), 0, MEM_RELEASE) == 0) diff --git a/source/emulator/src/Network.cpp b/source/emulator/src/Network.cpp index f8a079f..6e492d7 100644 --- a/source/emulator/src/Network.cpp +++ b/source/emulator/src/Network.cpp @@ -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 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();