diff --git a/include/revolution/SO/SOCommon.h b/include/revolution/SO/SOCommon.h index 8839144..1fc4a4e 100644 --- a/include/revolution/SO/SOCommon.h +++ b/include/revolution/SO/SOCommon.h @@ -72,8 +72,8 @@ typedef enum { typedef enum { SO_SO_REUSEADDR = 0x0004, - SO_SO_SNDBUF = 0x1002, - SO_SO_RCVBUF = 0x1003, + SO_SO_SNDBUF = 0x1001, + SO_SO_RCVBUF = 0x1002, } SOSockOpt; typedef enum { SO_SHUT_RD, SO_SHUT_WR, SO_SHUT_RDWR } SOShutdownType; diff --git a/lib/libkiwi/core/kiwiJSON.cpp b/lib/libkiwi/core/kiwiJSON.cpp index 2e1e7cd..04bf2dc 100644 --- a/lib/libkiwi/core/kiwiJSON.cpp +++ b/lib/libkiwi/core/kiwiJSON.cpp @@ -143,7 +143,7 @@ void Reader::DecodeImpl() { ParseEncoding(pos); } - // TODO: Implement UTF-16 parsing + // TODO(kiwi) Implement UTF-16 parsing K_ASSERT_EX(mEncoding == EEncoding_UTF8, "UTF-16 encoding is not yet supported"); @@ -1231,7 +1231,7 @@ void PrintVisitor::Visit(const Element& rElement) { it != rElement.Get().End(); ++it, i++) { Print('\"' + (it->key + "\": ")); - // TODO: Fix this somehow? + // TODO(kiwi) Fix this somehow? Visit(it->value); // Values are comma separated diff --git a/lib/libkiwi/core/kiwiJSON.h b/lib/libkiwi/core/kiwiJSON.h index b3e7792..2f2c230 100644 --- a/lib/libkiwi/core/kiwiJSON.h +++ b/lib/libkiwi/core/kiwiJSON.h @@ -153,7 +153,7 @@ class Element { K_ASSERT(mType == EType_Object); const Element* pElement = Get().Find(rKey); - // TODO: Better way to return a dummy element? + // TODO(kiwi) Better way to return a dummy element? if (pElement == nullptr) { static const Element undefined; return undefined; diff --git a/lib/libkiwi/core/kiwiJSONImpl.hpp b/lib/libkiwi/core/kiwiJSONImpl.hpp index 7f07336..4e35506 100644 --- a/lib/libkiwi/core/kiwiJSONImpl.hpp +++ b/lib/libkiwi/core/kiwiJSONImpl.hpp @@ -139,7 +139,7 @@ template <> K_INLINE void Element::Set(const Object& rValue) { /**@{*/ template <> K_INLINE Null_t& Element::Get() { K_ASSERT(mType == EType_Null); - // TODO: Better way to solve this problem? + // TODO(kiwi) Better way to solve this problem? return const_cast(json::null); } template <> K_INLINE const Null_t& Element::Get() const { diff --git a/lib/libkiwi/core/kiwiMemoryMgr.h b/lib/libkiwi/core/kiwiMemoryMgr.h index 0a69ae4..c26ca9c 100644 --- a/lib/libkiwi/core/kiwiMemoryMgr.h +++ b/lib/libkiwi/core/kiwiMemoryMgr.h @@ -82,7 +82,7 @@ class MemoryMgr : public StaticSingleton { EGG::Heap* GetHeap(EMemory memory) const; private: -// TODO: How to get more MEM1 memory from WS2? +// TODO(kiwi) How to get more MEM1 memory from WS2? #if defined(PACK_SPORTS) || defined(PACK_PLAY) //! Initial size for each heap static const u32 HEAP_SIZE = OS_MEM_KB_TO_B(1024); diff --git a/lib/libkiwi/core/kiwiThread.cpp b/lib/libkiwi/core/kiwiStdThread.cpp similarity index 75% rename from lib/libkiwi/core/kiwiThread.cpp rename to lib/libkiwi/core/kiwiStdThread.cpp index 775a8a8..71b3835 100644 --- a/lib/libkiwi/core/kiwiThread.cpp +++ b/lib/libkiwi/core/kiwiStdThread.cpp @@ -1,5 +1,3 @@ -#include - #include namespace kiwi { @@ -8,23 +6,24 @@ namespace detail { /** * @brief Constructor */ -ThreadImpl::ThreadImpl() : mpOSThread(nullptr), mpThreadStack(nullptr) { +StdThreadImpl::StdThreadImpl() : mpOSThread(nullptr), mpThreadStack(nullptr) { // Thread & stack aligned to 32 mpOSThread = new (32) OSThread(); K_ASSERT_PTR(mpOSThread); mpThreadStack = new (32) u8[scStackSize]; K_ASSERT_PTR(mpThreadStack); - BOOL success = - OSCreateThread(mpOSThread, nullptr, nullptr, - mpThreadStack + scStackSize, scStackSize, scPriority, 0); + BOOL success = OSCreateThread(mpOSThread, nullptr, nullptr, + mpThreadStack + scStackSize, scStackSize, + OS_PRIORITY_MAX - 1, 0); + K_ASSERT(success); } /** * @brief Destructor */ -ThreadImpl::~ThreadImpl() { +StdThreadImpl::~StdThreadImpl() { K_ASSERT_PTR(mpOSThread); K_ASSERT_EX(*mpOSThread->stackEnd == OS_THREAD_STACK_MAGIC, "Thread stack overflow!!!"); @@ -32,13 +31,13 @@ ThreadImpl::~ThreadImpl() { OSDetachThread(mpOSThread); delete mpOSThread; - delete mpThreadStack; + delete[] mpThreadStack; } /** * @brief Begins execution on this thread */ -void ThreadImpl::Start() { +void StdThreadImpl::Start() { K_ASSERT_PTR(mpOSThread); K_ASSERT(mpOSThread->state == OS_THREAD_STATE_READY); K_ASSERT_EX(mpOSThread->context.srr0 != 0, "No function to call"); @@ -51,7 +50,7 @@ void ThreadImpl::Start() { /** * @brief Waits for this thread to finish executing */ -void ThreadImpl::Join() { +void StdThreadImpl::Join() { K_ASSERT_PTR(mpOSThread); BOOL success = OSJoinThread(mpOSThread, nullptr); @@ -63,7 +62,7 @@ void ThreadImpl::Join() { * * @param addr Function address (new SRR0 value) */ -void ThreadImpl::SetFunction(const void* addr) { +void StdThreadImpl::SetFunction(const void* addr) { K_ASSERT_PTR(mpOSThread); K_ASSERT(addr != 0); mpOSThread->context.srr0 = BitCast(addr); @@ -75,7 +74,7 @@ void ThreadImpl::SetFunction(const void* addr) { * @param i GPR number * @param value New value */ -void ThreadImpl::SetGPR(u32 idx, u32 value) { +void StdThreadImpl::SetGPR(u32 idx, u32 value) { K_ASSERT_PTR(mpOSThread); K_ASSERT(idx >= 0 && idx < K_LENGTHOF(mpOSThread->context.gprs)); mpOSThread->context.gprs[idx] = value; diff --git a/lib/libkiwi/core/kiwiThread.h b/lib/libkiwi/core/kiwiStdThread.h similarity index 82% rename from lib/libkiwi/core/kiwiThread.h rename to lib/libkiwi/core/kiwiStdThread.h index c1f4578..e668ec4 100644 --- a/lib/libkiwi/core/kiwiThread.h +++ b/lib/libkiwi/core/kiwiStdThread.h @@ -1,5 +1,5 @@ -#ifndef LIBKIWI_CORE_THREAD_H -#define LIBKIWI_CORE_THREAD_H +#ifndef LIBKIWI_CORE_STD_THREAD_H +#define LIBKIWI_CORE_STD_THREAD_H #include #include @@ -16,7 +16,7 @@ namespace detail { /** * @brief Common thread implementation */ -class ThreadImpl { +class StdThreadImpl { public: /** * @brief Waits for this thread to finish executing @@ -27,11 +27,11 @@ class ThreadImpl { /** * @brief Constructor */ - ThreadImpl(); + StdThreadImpl(); /** * @brief Destructor */ - ~ThreadImpl(); + ~StdThreadImpl(); /** * @brief Begins execution on this thread @@ -77,7 +77,7 @@ class ThreadImpl { * @details Similar to std::thread. * @note Only allows GPR arguments */ -class Thread : public detail::ThreadImpl { +class StdThread : public detail::StdThreadImpl { public: // Thread function parameter typedef void* Param; @@ -92,14 +92,14 @@ class Thread : public detail::ThreadImpl { * * @param pFunc Static, no-parameter function */ - template Thread(TRet (*pFunc)()); + template StdThread(TRet (*pFunc)()); /** * @brief Constructor * * @param pFunc Static, single-parameter function * @param pArg Function argument */ - template Thread(TRet (*pFunc)(Param), Param pArg); + template StdThread(TRet (*pFunc)(Param), Param pArg); /**@}*/ /** @@ -113,7 +113,7 @@ class Thread : public detail::ThreadImpl { * @param rObj Class instance */ template - Thread(TRet (TClass::*pFunc)(), TClass& rObj); + StdThread(TRet (TClass::*pFunc)(), TClass& rObj); /** * @brief Constructor * @@ -122,7 +122,7 @@ class Thread : public detail::ThreadImpl { * @param pArg Function argument */ template - Thread(TRet (TClass::*pFunc)(Param), TClass& rObj, Param pArg); + StdThread(TRet (TClass::*pFunc)(Param), TClass& rObj, Param pArg); /**@}*/ /** @@ -136,7 +136,7 @@ class Thread : public detail::ThreadImpl { * @param rObj Class instance */ template - Thread(TRet (TClass::*pFunc)() const, const TClass& rObj); + StdThread(TRet (TClass::*pFunc)() const, const TClass& rObj); /** * @brief Constructor * @@ -145,7 +145,8 @@ class Thread : public detail::ThreadImpl { * @param pArg Function argument */ template - Thread(TRet (TClass::*pFunc)(Param) const, const TClass& rObj, Param pArg); + StdThread(TRet (TClass::*pFunc)(Param) const, const TClass& rObj, + Param pArg); /**@}*/ }; @@ -154,7 +155,7 @@ class Thread : public detail::ThreadImpl { // Implementation header #ifndef LIBKIWI_CORE_THREAD_IMPL_HPP -#include +#include #endif #endif diff --git a/lib/libkiwi/core/kiwiThreadImpl.hpp b/lib/libkiwi/core/kiwiStdThreadImpl.hpp similarity index 79% rename from lib/libkiwi/core/kiwiThreadImpl.hpp rename to lib/libkiwi/core/kiwiStdThreadImpl.hpp index 2403b59..dd90006 100644 --- a/lib/libkiwi/core/kiwiThreadImpl.hpp +++ b/lib/libkiwi/core/kiwiStdThreadImpl.hpp @@ -1,10 +1,10 @@ // Implementation header -#ifndef LIBKIWI_CORE_THREAD_IMPL_HPP -#define LIBKIWI_CORE_THREAD_IMPL_HPP +#ifndef LIBKIWI_CORE_STD_THREAD_IMPL_HPP +#define LIBKIWI_CORE_STD_THREAD_IMPL_HPP // Declaration header -#ifndef LIBKIWI_CORE_THREAD_H -#include +#ifndef LIBKIWI_CORE_STD_THREAD_H +#include #endif #include @@ -22,7 +22,7 @@ namespace kiwi { * * @param pFunc Static, no-parameter function */ -template Thread::Thread(TRet (*pFunc)()) { +template StdThread::StdThread(TRet (*pFunc)()) { K_ASSERT_PTR(pFunc); SetFunction(pFunc); @@ -36,7 +36,7 @@ template Thread::Thread(TRet (*pFunc)()) { * @param pArg Function argument */ template -Thread::Thread(TRet (*pFunc)(Thread::Param), Thread::Param pArg) { +StdThread::StdThread(TRet (*pFunc)(StdThread::Param), StdThread::Param pArg) { K_ASSERT_PTR(pFunc); SetFunction(pFunc); @@ -56,7 +56,7 @@ Thread::Thread(TRet (*pFunc)(Thread::Param), Thread::Param pArg) { * @param rObj Class instance */ template -Thread::Thread(TRet (TClass::*pFunc)(), TClass& rObj) { +StdThread::StdThread(TRet (TClass::*pFunc)(), TClass& rObj) { K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); @@ -71,8 +71,8 @@ Thread::Thread(TRet (TClass::*pFunc)(), TClass& rObj) { * @param pArg Function argument */ template -Thread::Thread(TRet (TClass::*pFunc)(Thread::Param), TClass& rObj, - Thread::Param pArg) { +StdThread::StdThread(TRet (TClass::*pFunc)(StdThread::Param), TClass& rObj, + StdThread::Param pArg) { K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); @@ -92,7 +92,7 @@ Thread::Thread(TRet (TClass::*pFunc)(Thread::Param), TClass& rObj, * @param rObj Class instance */ template -Thread::Thread(TRet (TClass::*pFunc)() const, const TClass& rObj) { +StdThread::StdThread(TRet (TClass::*pFunc)() const, const TClass& rObj) { K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); @@ -107,8 +107,8 @@ Thread::Thread(TRet (TClass::*pFunc)() const, const TClass& rObj) { * @param pArg Function argument */ template -Thread::Thread(TRet (TClass::*pFunc)(Thread::Param) const, const TClass& rObj, - Thread::Param pArg) { +StdThread::StdThread(TRet (TClass::*pFunc)(StdThread::Param) const, + const TClass& rObj, StdThread::Param pArg) { K_ASSERT(pFunc); SetMemberFunction(pFunc, rObj); @@ -139,8 +139,8 @@ struct MemberFunction { * @param rObj Class instance */ template -K_DONT_INLINE void ThreadImpl::SetMemberFunction(TFunc pFunc, - const TClass& rObj) { +K_DONT_INLINE void StdThreadImpl::SetMemberFunction(TFunc pFunc, + const TClass& rObj) { K_STATIC_ASSERT_EX(sizeof(TFunc) == sizeof(MemberFunction), "Not a member function"); diff --git a/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp b/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp index 46e828c..22b0db9 100644 --- a/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp +++ b/lib/libkiwi/debug/kiwiNw4rDirectPrint.cpp @@ -77,7 +77,7 @@ void Nw4rDirectPrint::SetupXfb() { // Initialize direct print SetColor(Color::WHITE); -// TODO: WS2 framebuffer is 608x456. Why? +// TODO(kiwi) WS2 framebuffer is 608x456. Why? #if defined(PACK_SPORTS) || defined(PACK_PLAY) // Try to repurpose current framebuffer void* pXfb = VIGetCurrentFrameBuffer(); diff --git a/lib/libkiwi/net/kiwiEmuRichPresenceClient.cpp b/lib/libkiwi/fun/kiwiEmuRichPresenceClient.cpp similarity index 100% rename from lib/libkiwi/net/kiwiEmuRichPresenceClient.cpp rename to lib/libkiwi/fun/kiwiEmuRichPresenceClient.cpp diff --git a/lib/libkiwi/net/kiwiEmuRichPresenceClient.h b/lib/libkiwi/fun/kiwiEmuRichPresenceClient.h similarity index 85% rename from lib/libkiwi/net/kiwiEmuRichPresenceClient.h rename to lib/libkiwi/fun/kiwiEmuRichPresenceClient.h index 1faf55b..11b8512 100644 --- a/lib/libkiwi/net/kiwiEmuRichPresenceClient.h +++ b/lib/libkiwi/fun/kiwiEmuRichPresenceClient.h @@ -1,11 +1,11 @@ -#ifndef LIBKIWI_NET_EMU_RICH_PRESENCE_CLIENT_H -#define LIBKIWI_NET_EMU_RICH_PRESENCE_CLIENT_H +#ifndef LIBKIWI_FUN_EMU_RICH_PRESENCE_CLIENT_H +#define LIBKIWI_FUN_EMU_RICH_PRESENCE_CLIENT_H +#include #include -#include #include namespace kiwi { -//! @addtogroup libkiwi_net +//! @addtogroup libkiwi_fun //! @{ /** diff --git a/lib/libkiwi/net/kiwiIRichPresenceClient.h b/lib/libkiwi/fun/kiwiIRichPresenceClient.h similarity index 97% rename from lib/libkiwi/net/kiwiIRichPresenceClient.h rename to lib/libkiwi/fun/kiwiIRichPresenceClient.h index fdfd824..e889c52 100644 --- a/lib/libkiwi/net/kiwiIRichPresenceClient.h +++ b/lib/libkiwi/fun/kiwiIRichPresenceClient.h @@ -1,10 +1,10 @@ -#ifndef LIBKIWI_NET_I_RICH_PRESENCE_CLIENT_H -#define LIBKIWI_NET_I_RICH_PRESENCE_CLIENT_H +#ifndef LIBKIWI_FUN_I_RICH_PRESENCE_CLIENT_H +#define LIBKIWI_FUN_I_RICH_PRESENCE_CLIENT_H #include #include namespace kiwi { -//! @addtogroup libkiwi_net +//! @addtogroup libkiwi_fun //! @{ /** diff --git a/lib/libkiwi/net/kiwiRichPresenceMgr.cpp b/lib/libkiwi/fun/kiwiRichPresenceMgr.cpp similarity index 97% rename from lib/libkiwi/net/kiwiRichPresenceMgr.cpp rename to lib/libkiwi/fun/kiwiRichPresenceMgr.cpp index 2854760..c6ad401 100644 --- a/lib/libkiwi/net/kiwiRichPresenceMgr.cpp +++ b/lib/libkiwi/fun/kiwiRichPresenceMgr.cpp @@ -10,7 +10,7 @@ namespace kiwi { RichPresenceMgr::RichPresenceMgr() : ISceneHook(-1), mpClient(nullptr), mpProfile(nullptr) { - // TODO: Only Dolphin Emulator is supported for now + // TODO(kiwi) Only Dolphin Emulator is supported for now mpClient = new EmuRichPresenceClient(); K_ASSERT_PTR(mpClient); diff --git a/lib/libkiwi/net/kiwiRichPresenceMgr.h b/lib/libkiwi/fun/kiwiRichPresenceMgr.h similarity index 95% rename from lib/libkiwi/net/kiwiRichPresenceMgr.h rename to lib/libkiwi/fun/kiwiRichPresenceMgr.h index 1751ae1..613a1c0 100644 --- a/lib/libkiwi/net/kiwiRichPresenceMgr.h +++ b/lib/libkiwi/fun/kiwiRichPresenceMgr.h @@ -1,5 +1,5 @@ -#ifndef LIBKIWI_NET_RICH_PRESENCE_MGR_H -#define LIBKIWI_NET_RICH_PRESENCE_MGR_H +#ifndef LIBKIWI_FUN_RICH_PRESENCE_MGR_H +#define LIBKIWI_FUN_RICH_PRESENCE_MGR_H #include #include #include @@ -8,6 +8,8 @@ #include namespace kiwi { +//! @addtogroup libkiwi_fun +//! @{ // Forward declarations class IRichPresenceClient; @@ -105,6 +107,7 @@ class RichPresenceMgr : public StaticSingleton, OSAlarm mAlarm; }; +//! @} } // namespace kiwi #endif diff --git a/lib/libkiwi/hostio/kiwiHostIOServer.cpp b/lib/libkiwi/hostio/kiwiHostIOServer.cpp index c4761e3..dee0e69 100644 --- a/lib/libkiwi/hostio/kiwiHostIOServer.cpp +++ b/lib/libkiwi/hostio/kiwiHostIOServer.cpp @@ -16,7 +16,7 @@ Server::Server() mpServerSocket(nullptr), mpClientSocket(nullptr) { - mpMainThread = new Thread(ThreadFunc, *this); + mpMainThread = new StdThread(ThreadFunc, *this); K_ASSERT_PTR(mpMainThread); } @@ -115,63 +115,63 @@ void Server::ThreadFunc() { void Server::EventLoop() { K_ASSERT_PTR(mpClientSocket); - while (true) { - // First four bytes specify the event data size - u32 eventSize = 0; - Optional nrecv = mpClientSocket->Recv(eventSize); - - // Connection failure - if (!nrecv) { - return; - } - - // Socket is blocking - if (*nrecv == 0) { - continue; - } - - // Sanity check packet size for corruption - K_ASSERT(eventSize < MAX_EVENT_BUFFER_SIZE); - Packet packet(eventSize); - - // Fill event packet data - while (!packet.IsWriteComplete()) { - // Optional nrecv = packet.Recv(*mpClientSocket); - - // if (!nrecv) { - // return; - // } - } - - // Can't process events without a node tree - if (mpRootNode == nullptr) { - continue; - } - - // Dispatch event to root node so it can propogate - const Event* pEvent = static_cast(packet.GetContent()); - mpRootNode->OnEvent(pEvent); - - // Root node may have generated a message in response - const MemStream& rStrm = mMessageContext.GetMessageStream(); - u32 msgSize = rStrm.GetSize(); - - // Send it off to the host client - if (msgSize > 0) { - Packet packet(msgSize); - - u32 written = packet.Write(rStrm.GetBuffer(), msgSize); - K_ASSERT(written == msgSize); - - while (!packet.IsReadComplete()) { - // Optional nsend = packet.Send(*mpClientSocket); - - // if (!nsend) { - // K_ASSERT_EX(false, "Send message error"); - // } - } - } - } + // while (true) { + // // First four bytes specify the event data size + // u32 eventSize = 0; + // Optional nrecv = mpClientSocket->Recv(eventSize); + + // // Connection failure + // if (!nrecv) { + // return; + // } + + // // Socket is blocking + // if (*nrecv == 0) { + // continue; + // } + + // // Sanity check packet size for corruption + // K_ASSERT(eventSize < MAX_EVENT_BUFFER_SIZE); + // Packet packet(eventSize); + + // // Fill event packet data + // while (!packet.IsWriteComplete()) { + // // Optional nrecv = packet.Recv(*mpClientSocket); + + // // if (!nrecv) { + // // return; + // // } + // } + + // // Can't process events without a node tree + // if (mpRootNode == nullptr) { + // continue; + // } + + // // Dispatch event to root node so it can propogate + // const Event* pEvent = static_cast(packet.GetContent()); + // mpRootNode->OnEvent(pEvent); + + // // Root node may have generated a message in response + // const MemStream& rStrm = mMessageContext.GetMessageStream(); + // u32 msgSize = rStrm.GetSize(); + + // // Send it off to the host client + // if (msgSize > 0) { + // Packet packet(msgSize); + + // u32 written = packet.Write(rStrm.GetBuffer(), msgSize); + // K_ASSERT(written == msgSize); + + // while (!packet.IsReadComplete()) { + // // Optional nsend = packet.Send(*mpClientSocket); + + // // if (!nsend) { + // // K_ASSERT_EX(false, "Send message error"); + // // } + // } + // } + // } } } // namespace hostio diff --git a/lib/libkiwi/hostio/kiwiHostIOServer.h b/lib/libkiwi/hostio/kiwiHostIOServer.h index 23ab08c..14e323c 100644 --- a/lib/libkiwi/hostio/kiwiHostIOServer.h +++ b/lib/libkiwi/hostio/kiwiHostIOServer.h @@ -1,6 +1,5 @@ #ifndef LIBKIWI_HOSTIO_HOST_IO_SERVER_H #define LIBKIWI_HOSTIO_HOST_IO_SERVER_H -#include #include #include #include @@ -12,6 +11,10 @@ namespace kiwi { //! @addtogroup libkiwi_hostio //! @{ + +// Forward declarations +class StdThread; + namespace hostio { //! @addtogroup libkiwi_hostio //! @{ @@ -89,7 +92,7 @@ class Server : public DynamicSingleton { Reflexible* mpRootNode; //! Main loop thread - Thread* mpMainThread; + StdThread* mpMainThread; //! Server socket SyncSocket* mpServerSocket; diff --git a/lib/libkiwi/libkiwi.h b/lib/libkiwi/libkiwi.h index 0f0fcee..6820dac 100644 --- a/lib/libkiwi/libkiwi.h +++ b/lib/libkiwi/libkiwi.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -34,7 +34,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -48,18 +51,23 @@ #include #include #include -#include +#include #include -#include -#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include #include #include -#include +#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/lib/libkiwi/math/kiwiAlgorithm.h b/lib/libkiwi/math/kiwiAlgorithm.h index 7f7895b..0af6803 100644 --- a/lib/libkiwi/math/kiwiAlgorithm.h +++ b/lib/libkiwi/math/kiwiAlgorithm.h @@ -226,7 +226,7 @@ K_INLINE void UnShuffle(const TKey (&rKeys)[KeyNum], TElem (&rArray)[ElemNum]) { continue; } - // TODO: Binary search through the keys? + // TODO(kiwi) Binary search through the keys? for (u32 j = 0; j < KeyNum; j++) { if (rArray[i] == rKeys[j]) { std::swap(rArray[i], rArray[rArray[i]]); diff --git a/lib/libkiwi/net/kiwiAsyncSocket.cpp b/lib/libkiwi/net/kiwiAsyncSocket.cpp index da227e3..7ec20ed 100644 --- a/lib/libkiwi/net/kiwiAsyncSocket.cpp +++ b/lib/libkiwi/net/kiwiAsyncSocket.cpp @@ -2,253 +2,417 @@ namespace kiwi { -/** - * @brief Socket manager thread - */ -OSThread AsyncSocket::sSocketThread; +/****************************************************************************** + * + * IJob + * + ******************************************************************************/ /** - * @brief Thread guard + * @brief Asynchronous job interface */ -bool AsyncSocket::sSocketThreadCreated = false; +class AsyncSocket::IJob { +public: + /** + * @brief Destructor + */ + virtual ~IJob() {} -/** - * @brief Thread stack - */ -u8 AsyncSocket::sSocketThreadStack[scThreadStackSize]; + /** + * @brief Updates the job state + * + * @return Whether the job has completed + */ + virtual bool Calc() = 0; +}; -/** - * @brief Open async sockets - */ -TList AsyncSocket::sSocketList; +/****************************************************************************** + * + * ConnectJob + * + ******************************************************************************/ /** - * @brief Async receive operation + * @brief Asynchronous connect job */ -class AsyncSocket::RecvJob { +class AsyncSocket::ConnectJob : public IJob { public: /** * @brief Constructor * - * @param pPacket Packet for this job - * @param pDst Destination address - * @param[out] pPeer Peer address - * @param pCallback Completion callback + * @param pAsyncSocket Parent socket + * @param pPeerAddr Peer address + * @param pCallback Connect callback * @param pArg Callback user argument */ - RecvJob(Packet* pPacket, void* pDst, SockAddrAny* pPeer, - Callback pCallback = nullptr, void* pArg = nullptr) - : mpPacket(pPacket), - mpDst(pDst), - mpPeer(pPeer), + ConnectJob(AsyncSocket* pAsyncSocket, const SockAddrAny& rPeerAddr, + ConnectCallback pCallback, void* pArg) + : mpSocket(nullptr), + mPeerAddr(rPeerAddr), mpCallback(pCallback), mpArg(pArg) { - K_ASSERT_PTR(mpPacket); - K_ASSERT_PTR(mpDst); - K_ASSERT(OSIsMEM2Region(mpDst)); + K_ASSERT_PTR(pAsyncSocket); + K_ASSERT_PTR(mpCallback); + K_ASSERT(mPeerAddr.IsValid()); + + // Need synchronous socket for internal communication + mpSocket = new SyncSocket(pAsyncSocket->mHandle, pAsyncSocket->mFamily, + pAsyncSocket->mType); + K_ASSERT_PTR(mpSocket); + + mpSocket->SetBlocking(false); } /** * @brief Destructor */ - ~RecvJob() { - delete mpPacket; + virtual ~ConnectJob() { + delete mpSocket; + mpSocket = nullptr; } /** - * @brief Tests whether the receive operation is complete + * @brief Updates the job state + * + * @return Whether the job has completed */ - bool IsComplete() const { - K_ASSERT_PTR(mpPacket); - return mpPacket->IsWriteComplete(); + virtual bool Calc() { + K_ASSERT_PTR(mpSocket); + K_ASSERT(mPeerAddr.IsValid()); + + bool success = mpSocket->Connect(mPeerAddr); + SOResult result = LibSO::GetLastError(); + + // Blocking, try again later + if (result == SO_EWOULDBLOCK) { + return false; + } + + K_ASSERT_PTR(mpCallback); + mpCallback(result, mpArg); + + // Terminate job regardless of success + return true; } +private: + //! Temporary socket for synchronous communication + SyncSocket* mpSocket; + //! Target peer address + SockAddrAny mPeerAddr; + + //! Connect callback + ConnectCallback mpCallback; + //! Callback user argument + void* mpArg; +}; + +/****************************************************************************** + * + * AcceptJob + * + ******************************************************************************/ + +/** + * @brief Asynchronous accept job + */ +class AsyncSocket::AcceptJob : public IJob { +public: /** - * @brief Updates job using the specified socket + * @brief Constructor * - * @param socket Socket descriptor - * @return Whether the job is complete + * @param pAsyncSocket Parent socket + * @param pSrc Source buffer + * @param len Buffer size + * @param pCallback Transfer callback + * @param pArg Callback user argument */ - bool Calc(SOSocket socket) { - K_ASSERT_PTR(mpPacket); - K_ASSERT(socket >= 0); + AcceptJob(AsyncSocket* pAsyncSocket, AcceptCallback pCallback, void* pArg) + : mpSocket(nullptr), mpCallback(pCallback), mpArg(pArg) { - // Nothing left to do - if (IsComplete()) { - return true; - } + K_ASSERT_PTR(pAsyncSocket); + K_ASSERT_PTR(mpCallback); - // Update - mpPacket->Recv(socket); - bool done = IsComplete(); + // Need synchronous socket for internal communication + mpSocket = new SyncSocket(pAsyncSocket->mHandle, pAsyncSocket->mFamily, + pAsyncSocket->mType); + K_ASSERT_PTR(mpSocket); + } - // Write out data - if (done) { - K_ASSERT_PTR(mpDst); - K_ASSERT(OSIsMEM2Region(mpDst)); + /** + * @brief Destructor + */ + virtual ~AcceptJob() { + delete mpSocket; + mpSocket = nullptr; + } - std::memcpy(mpDst, mpPacket->GetContent(), - mpPacket->GetContentSize()); + /** + * @brief Updates the job state + * + * @return Whether the job has completed + */ + virtual bool Calc() { + K_ASSERT_PTR(mpSocket); - // Write peer information - if (mpPeer != nullptr) { - *mpPeer = mpPacket->GetPeer(); - } + SocketBase* pPeerSocket = mpSocket->Accept(); + SOResult result = LibSO::GetLastError(); - // Notify user - if (mpCallback != nullptr) { - mpCallback(LibSO::GetLastError(), mpArg); - } + // Blocking, try again later + if (result == SO_EWOULDBLOCK) { + return false; + } + + // TODO(kiwi) Can we get this through the callback? + SockAddrAny addr; + if (pPeerSocket != nullptr) { + bool success = mpSocket->GetPeerAddr(addr); + K_ASSERT(success); } - return done; + K_ASSERT_PTR(mpCallback); + mpCallback(result, pPeerSocket, addr, mpArg); + + // Terminate job regardless of success + return true; } private: - Packet* mpPacket; // Packet to complete - void* mpDst; // Where to store packet data - SOSockAddr* mpPeer; // Where to store peer address + //! Temporary socket for synchronous communication + SyncSocket* mpSocket; - Callback mpCallback; // Completion callback - void* mpArg; // Completion callback user argument + //! Accept callback + AcceptCallback mpCallback; + //! Callback user argument + void* mpArg; }; +/****************************************************************************** + * + * RecvJob + * + ******************************************************************************/ + /** - * @brief Async send operation + * @brief Asynchronous receive job */ -class AsyncSocket::SendJob { +class AsyncSocket::RecvJob : public IJob { public: /** * @brief Constructor * - * @param pPacket Packet for this job - * @param pCallback Completion callback + * @param pAsyncSocket Parent socket + * @param pDst Destination buffer + * @param len Buffer size + * @param[out] pPeerAddr Peer address + * @param pCallback Transfer callback * @param pArg Callback user argument */ - SendJob(Packet* pPacket, Callback pCallback = nullptr, void* pArg = nullptr) - : mpPacket(pPacket), mpCallback(pCallback), mpArg(pArg) { + RecvJob(AsyncSocket* pAsyncSocket, void* pDst, u32 len, + SockAddrAny* pPeerAddr, XferCallback pCallback, void* pArg) + : mpSocket(nullptr), + mpPacket(nullptr), + mpDst(pDst), + mpPeerAddr(pPeerAddr), + mpCallback(pCallback), + mpArg(pArg) { - K_ASSERT_PTR(mpPacket); + K_ASSERT_PTR(pAsyncSocket); + K_ASSERT_PTR(mpDst); + K_ASSERT(!PtrUtil::IsStack(mpDst)); + K_ASSERT(mpPeerAddr == nullptr || !PtrUtil::IsStack(mpPeerAddr)); + K_ASSERT_PTR(mpCallback); + + // Need synchronous socket for internal communication + mpSocket = new SyncSocket(pAsyncSocket->mHandle, pAsyncSocket->mFamily, + pAsyncSocket->mType); + K_ASSERT_PTR(mpSocket); + + mpPacket = new FixedPacket(); + mpPacket->Alloc(len); + mpPacket->Recv(mpSocket); } /** * @brief Destructor */ - ~SendJob() { - delete mpPacket; - } + virtual ~RecvJob() { + delete mpSocket; + mpSocket = nullptr; - /** - * @brief Tests whether the send operation is complete - */ - bool IsComplete() const { - K_ASSERT_PTR(mpPacket); - return mpPacket->IsReadComplete(); + delete mpPacket; + mpPacket = nullptr; } /** - * @brief Updates job using the specified socket + * @brief Updates the job state * - * @param socket Socket descriptor - * @return Whether the job is complete + * @return Whether the job has completed */ - bool Calc(SOSocket socket) { + virtual bool Calc() { K_ASSERT_PTR(mpPacket); - K_ASSERT(socket >= 0); - // Nothing left to do - if (IsComplete()) { - return true; - } + bool finish = mpPacket->Calc(); + SOResult result = LibSO::GetLastError(); - // Update - mpPacket->Send(socket); - bool done = IsComplete(); + if (finish) { + std::memcpy(mpDst, mpPacket->GetContent(), + mpPacket->GetContentSize()); + + if (mpPeerAddr != nullptr) { + *mpPeerAddr = mpPacket->GetPeerAddr(); + } - // Fire callback - if (done && mpCallback != nullptr) { - mpCallback(LibSO::GetLastError(), mpArg); + K_ASSERT_PTR(mpCallback); + mpCallback(result, mpPacket->GetContentSize(), mpArg); } - return done; + return finish; } private: - Packet* mpPacket; // Packet to complete - - Callback mpCallback; // Completion callback - void* mpArg; // Completion callback user argument + //! Temporary socket for synchronous communication + SyncSocket* mpSocket; + //! Raw data packet + FixedPacket* mpPacket; + + //! Destination buffer + void* mpDst; + //! Destination for peer address + SockAddrAny* mpPeerAddr; + + //! Transfer callback + XferCallback mpCallback; + //! Callback user argument + void* mpArg; }; -/** - * @brief Socket thread function +/****************************************************************************** + * + * SendJob * - * @param pArg Thread function argument + ******************************************************************************/ + +/** + * @brief Asynchronous send job */ -void* AsyncSocket::ThreadFunc(void* pArg) { -#pragma unused(pArg) - - // Update all open sockets - while (true) { - K_FOREACH (it, sSocketList) { - K_ASSERT((*it)->IsOpen()); - (*it)->Calc(); +class AsyncSocket::SendJob : public IJob { +public: + /** + * @brief Constructor + * + * @param pAsyncSocket Parent socket + * @param pSrc Source buffer + * @param len Buffer size + * @param pPeerAddr Peer address + * @param pCallback Transfer callback + * @param pArg Callback user argument + */ + SendJob(AsyncSocket* pAsyncSocket, const void* pSrc, u32 len, + const SockAddrAny* pPeerAddr, XferCallback pCallback = nullptr, + void* pArg = nullptr) + : mpSocket(nullptr), + mpPacket(nullptr), + mpCallback(pCallback), + mpArg(pArg) { + + K_ASSERT_PTR(pAsyncSocket); + K_ASSERT_PTR(pSrc); + K_ASSERT(!PtrUtil::IsStack(pSrc)); + K_ASSERT_PTR(mpCallback); + + // Need synchronous socket for internal communication + mpSocket = new SyncSocket(pAsyncSocket->mHandle, pAsyncSocket->mFamily, + pAsyncSocket->mType); + K_ASSERT_PTR(mpSocket); + + mpPacket = new FixedPacket(pPeerAddr); + mpPacket->Alloc(len); + mpPacket->SetContent(pSrc, len); + mpPacket->Send(mpSocket); + } + + /** + * @brief Destructor + */ + virtual ~SendJob() { + delete mpSocket; + mpSocket = nullptr; + + delete mpPacket; + mpPacket = nullptr; + } + + /** + * @brief Updates the job state + * + * @return Whether the job has completed + */ + virtual bool Calc() { + K_ASSERT_PTR(mpPacket); + + bool finish = mpPacket->Calc(); + SOResult result = LibSO::GetLastError(); + + if (finish) { + K_ASSERT_PTR(mpCallback); + mpCallback(result, mpPacket->GetContentSize(), mpArg); } + + return finish; } - return nullptr; -} +private: + //! Temporary socket for synchronous communication + SyncSocket* mpSocket; + //! Raw data packet + FixedPacket* mpPacket; + + //! Transfer callback + XferCallback mpCallback; + //! Callback user argument + void* mpArg; +}; -/** - * @brief Constructor +/****************************************************************************** * - * @param family Socket protocol family - * @param type Socket type - */ -AsyncSocket::AsyncSocket(SOProtoFamily family, SOSockType type) - : SocketBase(family, type), - mState(EState_Thinking), - mpConnectCallback(nullptr), - mpConnectCallbackArg(nullptr), - mpAcceptCallback(nullptr), - mpAcceptCallbackArg(nullptr) { - Initialize(); -} + * AsyncSocket + * + ******************************************************************************/ /** - * @brief Constructor - * - * @param socket Socket file descriptor - * @param type Socket protocol family - * @param type Socket type + * @brief Destructor */ -AsyncSocket::AsyncSocket(SOSocket socket, SOProtoFamily family, SOSockType type) - : SocketBase(socket, family, type), - mState(EState_Thinking), - mpConnectCallback(nullptr), - mpConnectCallbackArg(nullptr), - mpAcceptCallback(nullptr), - mpAcceptCallbackArg(nullptr) { - Initialize(); +AsyncSocket::~AsyncSocket() { + detail::AsyncSocketMgr::GetInstance().RemoveSocket(this); + + // Release memory for receive jobs + for (TList::Iterator it = mRecvJobs.Begin(); + it != mRecvJobs.End();) { + + TList::Iterator curr = it++; + delete &*curr; + } + + // Release memory for send jobs + for (TList::Iterator it = mSendJobs.Begin(); + it != mSendJobs.End();) { + + TList::Iterator curr = it++; + delete &*curr; + } } /** - * @brief Prepares socket for async operation + * @brief Initializes socket state */ -void AsyncSocket::Initialize() { - // Thread needs to see this socket - sSocketList.PushBack(this); - - // Thread must exist if there is an open socket - if (!sSocketThreadCreated) { - OSCreateThread(&sSocketThread, ThreadFunc, nullptr, - sSocketThreadStack + sizeof(sSocketThreadStack), - sizeof(sSocketThreadStack), OS_PRIORITY_MAX, 0); - - sSocketThreadCreated = true; - OSResumeThread(&sSocketThread); - } +void AsyncSocket::Init() { + mStateMachine.RegistState(EState_Idle, &AsyncSocket::State_Idle_calc); + mStateMachine.RegistState(EState_Accept, &AsyncSocket::State_Accept_calc); + mStateMachine.RegistState(EState_Connect, &AsyncSocket::State_Connect_calc); + + detail::AsyncSocketMgr::GetInstance().AddSocket(this); } /** @@ -259,15 +423,15 @@ void AsyncSocket::Initialize() { * @param pArg Callback user argument * @return Success */ -bool AsyncSocket::Connect(const SockAddrAny& rAddr, Callback pCallback, +bool AsyncSocket::Connect(const SockAddrAny& rAddr, ConnectCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); - mState = EState_Connecting; - mPeer = rAddr; + ConnectJob* pJob = new ConnectJob(this, rAddr, pCallback, pArg); + K_ASSERT_PTR(pJob); - mpConnectCallback = pCallback; - mpConnectCallbackArg = pArg; + mpConnectJob = pJob; + mStateMachine.ChangeState(EState_Connect); // Connect doesn't actually happen on this thread return false; @@ -283,110 +447,68 @@ bool AsyncSocket::Connect(const SockAddrAny& rAddr, Callback pCallback, AsyncSocket* AsyncSocket::Accept(AcceptCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); - mState = EState_Accepting; + AcceptJob* pJob = new AcceptJob(this, pCallback, pArg); + K_ASSERT_PTR(pJob); - mpAcceptCallback = pCallback; - mpAcceptCallbackArg = pArg; + mpAcceptJob = pJob; + mStateMachine.ChangeState(EState_Accept); // Accept doesn't actually happen on this thread return nullptr; } /** - * @brief Processes pending socket tasks + * @brief Updates the packet in the Idle state */ -void AsyncSocket::Calc() { - s32 result; - +void AsyncSocket::State_Idle_calc() { K_ASSERT(IsOpen()); - switch (mState) { - case EState_Thinking: - CalcRecv(); - CalcSend(); - break; - - case EState_Connecting: - result = LibSO::Connect(mHandle, mPeer); + // Update the oldest receive job + if (!mRecvJobs.Empty()) { + RecvJob& rJob = *static_cast(mRecvJobs.Front()); - // Blocking, try again - if (result == SO_EINPROGRESS || result == SO_EALREADY) { - break; + if (rJob.Calc()) { + mRecvJobs.PopFront(); + delete &rJob; } + } - // Connection complete (looking for EISCONN here) - mState = EState_Thinking; - mpConnectCallback(result == SO_EISCONN ? SO_SUCCESS - : LibSO::GetLastError(), - mpConnectCallbackArg); - - break; - - case EState_Accepting: - result = LibSO::Accept(mHandle, mPeer); - - // Report non-blocking results - if (result != SO_EWOULDBLOCK) { - // Peer connection - AsyncSocket* pSocket = nullptr; - - // Result code is the peer descriptor - if (result >= 0) { - pSocket = new AsyncSocket(result, mFamily, mType); - K_ASSERT_PTR(pSocket); - } + // Update the oldest send job + if (!mSendJobs.Empty()) { + SendJob& rJob = *static_cast(mSendJobs.Front()); - mState = EState_Thinking; - mpAcceptCallback(LibSO::GetLastError(), pSocket, mPeer, - mpAcceptCallbackArg); + if (rJob.Calc()) { + mSendJobs.PopFront(); + delete &rJob; } - break; } } /** - * @brief Receives packet data over socket + * @brief Updates the packet in the Connect state */ -void AsyncSocket::CalcRecv() { +void AsyncSocket::State_Connect_calc() { K_ASSERT(IsOpen()); - // Nothing to do - if (mRecvJobs.Empty()) { - return; - } - - // Find next incomplete job (FIFO) - RecvJob& rJob = *mRecvJobs.Front(); - K_ASSERT_EX(!rJob.IsComplete(), "Completed job should be removed"); + if (mpConnectJob != nullptr && mpConnectJob->Calc()) { + delete mpConnectJob; + mpConnectJob = nullptr; - // Attempt to complete job - if (rJob.Calc(mHandle)) { - // Remove from queue - mRecvJobs.PopFront(); - delete &rJob; + mStateMachine.ChangeState(EState_Idle); } } /** - * @brief Sends packet data over socket + * @brief Updates the packet in the Accept state */ -void AsyncSocket::CalcSend() { +void AsyncSocket::State_Accept_calc() { K_ASSERT(IsOpen()); - // Nothing to do - if (mSendJobs.Empty()) { - return; - } + if (mpAcceptJob != nullptr && mpAcceptJob->Calc()) { + delete mpAcceptJob; + mpAcceptJob = nullptr; - // Find next incomplete job (FIFO) - SendJob& rJob = *mSendJobs.Front(); - K_ASSERT_EX(!rJob.IsComplete(), "Completed job should be removed"); - - // Attempt to complete job - if (rJob.Calc(mHandle)) { - // Remove from queue - mSendJobs.PopFront(); - delete &rJob; + mStateMachine.ChangeState(EState_Idle); } } @@ -402,18 +524,17 @@ void AsyncSocket::CalcSend() { * @return Socket library result */ SOResult AsyncSocket::RecvImpl(void* pDst, u32 len, u32& rRecv, - SockAddrAny* pAddr, Callback pCallback, + SockAddrAny* pAddr, XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pDst); - K_ASSERT(OSIsMEM2Region(pDst)); + K_ASSERT_PTR(pCallback); - // Packet to hold incoming data - Packet* pPacket = new Packet(len); - K_ASSERT_PTR(pPacket); + // Not actually required but enforced for consistency with other sockets + K_ASSERT(OSIsMEM2Region(pDst)); // Asynchronous job - RecvJob* pJob = new RecvJob(pPacket, pDst, pAddr, pCallback, pArg); + RecvJob* pJob = new RecvJob(this, pDst, len, pAddr, pCallback, pArg); K_ASSERT_PTR(pJob); mRecvJobs.PushBack(pJob); @@ -434,21 +555,17 @@ SOResult AsyncSocket::RecvImpl(void* pDst, u32 len, u32& rRecv, * @return Socket library result */ SOResult AsyncSocket::SendImpl(const void* pSrc, u32 len, u32& rSend, - const SockAddrAny* pAddr, Callback pCallback, + const SockAddrAny* pAddr, XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pSrc); - K_ASSERT(OSIsMEM2Region(pSrc)); + K_ASSERT_PTR(pCallback); - // Packet to hold incoming data - Packet* pPacket = new Packet(len, pAddr); - K_ASSERT_PTR(pPacket); - - // Store data inside packet - pPacket->Write(pSrc, len); + // Not actually required but enforced for consistency with other sockets + K_ASSERT(OSIsMEM2Region(pSrc)); // Asynchronous job - SendJob* pJob = new SendJob(pPacket, pCallback, pArg); + SendJob* pJob = new SendJob(this, pSrc, len, pAddr, pCallback, pArg); K_ASSERT_PTR(pJob); mSendJobs.PushBack(pJob); diff --git a/lib/libkiwi/net/kiwiAsyncSocket.h b/lib/libkiwi/net/kiwiAsyncSocket.h index 6ac2430..b1410e3 100644 --- a/lib/libkiwi/net/kiwiAsyncSocket.h +++ b/lib/libkiwi/net/kiwiAsyncSocket.h @@ -1,8 +1,10 @@ #ifndef LIBKIWI_NET_ASYNC_SOCKET_H #define LIBKIWI_NET_ASYNC_SOCKET_H #include +#include #include #include +#include #include @@ -10,13 +12,17 @@ namespace kiwi { //! @addtogroup libkiwi_net //! @{ +// Forward declarations +namespace detail { +class AsyncSocketMgr; +} // namespace detail + /** * @brief Asynchronous socket */ class AsyncSocket : public SocketBase { -public: - using SocketBase::AcceptCallback; - using SocketBase::Callback; + // Expose Calc only to the manager + friend class detail::AsyncSocketMgr; public: /** @@ -25,15 +31,32 @@ class AsyncSocket : public SocketBase { * @param family Socket protocol family * @param type Socket type */ - AsyncSocket(SOProtoFamily family, SOSockType type); + AsyncSocket(SOProtoFamily family, SOSockType type) + : SocketBase(family, type), + mStateMachine(this, EState_Max, EState_Idle) { + + Init(); + } /** - * @brief Destructor + * @brief Constructor + * + * @param socket Socket file descriptor + * @param type Socket protocol family + * @param type Socket type */ - virtual ~AsyncSocket() { - sSocketList.Remove(this); + AsyncSocket(SOSocket socket, SOProtoFamily family, SOSockType type) + : SocketBase(socket, family, type), + mStateMachine(this, EState_Max, EState_Idle) { + + Init(); } + /** + * @brief Destructor + */ + virtual ~AsyncSocket(); + /** * @brief Connects to a peer * @@ -42,7 +65,7 @@ class AsyncSocket : public SocketBase { * @param pArg Callback user argument * @return Success */ - virtual bool Connect(const SockAddrAny& rAddr, Callback pCallback, + virtual bool Connect(const SockAddrAny& rAddr, ConnectCallback pCallback, void* pArg); /** @@ -56,49 +79,62 @@ class AsyncSocket : public SocketBase { private: /** - * @brief Async state + * @brief State machine state */ - enum EState { EState_Thinking, EState_Connecting, EState_Accepting }; + enum EState { + EState_Idle, //!< Process send/recv jobs + EState_Connect, //!< Trying to connect to peer + EState_Accept, //!< Trying to accept peer + + EState_Max + }; + + //! Asynchronous job interface + class IJob; + + //! Asynchronous connect job + class ConnectJob; + friend class ConnectJob; - //! Async receive operation + //! Asynchronous accept job + class AcceptJob; + friend class AcceptJob; + + //! Asynchronous receive job class RecvJob; - //! Async send operation + friend class RecvJob; + + //! Asynchronous send job class SendJob; + friend class SendJob; private: /** - * @brief Socket thread function - * - * @param pArg Thread function argument + * @brief Initializes socket state */ - static void* ThreadFunc(void* pArg); + void Init(); /** - * @brief Constructor - * - * @param socket Socket file descriptor - * @param type Socket protocol family - * @param type Socket type + * @brief Updates the socket state */ - AsyncSocket(SOSocket socket, SOProtoFamily family, SOSockType type); + void Calc() { + mStateMachine.Calculate(); + } /** - * @brief Prepares socket for async operation + * @brief Updates the packet in the Idle state */ - void Initialize(); - /** - * @brief Processes pending socket tasks - */ - void Calc(); + K_STATE_DECL(Idle); /** - * @brief Receives packet data over socket + * @brief Updates the packet in the Connect state */ - void CalcRecv(); + K_STATE_DECL(Connect); + /** - * @brief Sends packet data over socket + * @brief Updates the packet in the Accept state */ - void CalcSend(); + K_STATE_DECL(Accept); /** * @brief Receives data and records sender address (internal implementation) @@ -112,7 +148,7 @@ class AsyncSocket : public SocketBase { * @return Socket library result */ virtual SOResult RecvImpl(void* pDst, u32 len, u32& rRecv, - SockAddrAny* pAddr, Callback pCallback, + SockAddrAny* pAddr, XferCallback pCallback, void* pArg); /** @@ -127,34 +163,22 @@ class AsyncSocket : public SocketBase { * @return Socket library result */ virtual SOResult SendImpl(const void* pSrc, u32 len, u32& rSend, - const SockAddrAny* pAddr, Callback pCallback, + const SockAddrAny* pAddr, XferCallback pCallback, void* pArg); private: - //! Socket manager thread stack size - static const u32 scThreadStackSize = 0x4000; - - volatile EState mState; //!< Current async task - SockAddrAny mPeer; //!< Peer address - - TList mRecvJobs; //!< Active receive jobs - TList mSendJobs; //!< Active send jobs - - Callback mpConnectCallback; //!< Connect callback - void* mpConnectCallbackArg; //!< Connect callback user argument - - AcceptCallback mpAcceptCallback; //!< Accept callback - void* mpAcceptCallbackArg; //!< Accept callback user argument - - //! Socket manager thread - static OSThread sSocketThread; - //! Thread guard - static bool sSocketThreadCreated; - //! Thread stack - static u8 sSocketThreadStack[scThreadStackSize]; - - //! Open async sockets - static TList sSocketList; + //! Logic state machine + StateMachine mStateMachine; + + //! Active connect job + IJob* mpConnectJob; + //! Active accept job + IJob* mpAcceptJob; + + //! Active receive jobs + TList mRecvJobs; + //! Active send jobs + TList mSendJobs; }; //! @} diff --git a/lib/libkiwi/net/kiwiAsyncSocketMgr.cpp b/lib/libkiwi/net/kiwiAsyncSocketMgr.cpp new file mode 100644 index 0000000..8619fdf --- /dev/null +++ b/lib/libkiwi/net/kiwiAsyncSocketMgr.cpp @@ -0,0 +1,34 @@ +#include + +namespace kiwi { +namespace detail { + +/** + * @brief Constructor + */ +AsyncSocketMgr::AsyncSocketMgr() { + mpThread = new StdThread(&AsyncSocketMgr::ThreadFunc, *this); +} + +/** + * @brief Destructor + */ +AsyncSocketMgr::~AsyncSocketMgr() { + delete mpThread; + mpThread = nullptr; +} + +/** + * @brief Thread function + */ +void AsyncSocketMgr::ThreadFunc() { + while (true) { + K_FOREACH (it, mSocketList) { + K_ASSERT((*it)->IsOpen()); + (*it)->Calc(); + } + } +} + +} // namespace detail +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/net/kiwiAsyncSocketMgr.h b/lib/libkiwi/net/kiwiAsyncSocketMgr.h new file mode 100644 index 0000000..59f73b8 --- /dev/null +++ b/lib/libkiwi/net/kiwiAsyncSocketMgr.h @@ -0,0 +1,74 @@ +#ifndef LIBKIWI_NET_ASYNC_SOCKET_MGR_H +#define LIBKIWI_NET_ASYNC_SOCKET_MGR_H +#include +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class AsyncSocket; +class StdThread; + +namespace detail { +//! @addtogroup libkiwi_net +//! @{ + +/** + * @brief Asynchronous socket manager + */ +class AsyncSocketMgr : public StaticSingleton { + friend class StaticSingleton; + +public: + /** + * @brief Appends a new socket to the manager list + * + * @param pSocket New socket + */ + void AddSocket(AsyncSocket* pSocket) { + K_ASSERT_PTR(pSocket); + mSocketList.PushBack(pSocket); + } + + /** + * @brief Removes a socket from the manager list + * + * @param pSocket Socket + */ + void RemoveSocket(AsyncSocket* pSocket) { + mSocketList.Remove(pSocket); + } + +private: + /** + * @brief Constructor + */ + AsyncSocketMgr(); + + /** + * @brief Destructor + */ + ~AsyncSocketMgr(); + + /** + * @brief Thread function + */ + void ThreadFunc(); + +private: + //! Manager thread + StdThread* mpThread; + //! Open sockets + TList mSocketList; +}; + +//! @} +} // namespace detail +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiHttpRequest.cpp b/lib/libkiwi/net/kiwiHttpRequest.cpp index 996eb04..3fe2991 100644 --- a/lib/libkiwi/net/kiwiHttpRequest.cpp +++ b/lib/libkiwi/net/kiwiHttpRequest.cpp @@ -99,7 +99,7 @@ void HttpRequest::SendAsync(Callback pCallback, void* pArg, EMethod method) { mpCallback = pCallback; mpCallbackArg = pArg; - // TODO: Need state machine for request/receive (can reuse for synchronous) + // TODO(kiwi) Need state machine for request/receive K_NOT_IMPLEMENTED(); // Thread t(SendImpl, *this); } diff --git a/lib/libkiwi/net/kiwiHttpRequest.h b/lib/libkiwi/net/kiwiHttpRequest.h index 4759f91..3672967 100644 --- a/lib/libkiwi/net/kiwiHttpRequest.h +++ b/lib/libkiwi/net/kiwiHttpRequest.h @@ -30,7 +30,7 @@ enum EHttpErr { * @brief HTTP status code */ enum EHttpStatus { - // TODO: Determine which additional codes are useful here + // TODO(kiwi) Determine which additional codes are useful here EHttpStatus_None = -1, // Informational @@ -77,7 +77,7 @@ struct HttpResponse { * @brief HTTP (1.1) request wrapper */ class HttpRequest { - // TODO: How to fix this... bad relationship + // TODO(kiwi) How to fix this... bad relationship friend class WebSocket; public: diff --git a/lib/libkiwi/net/kiwiNetBuffer.cpp b/lib/libkiwi/net/kiwiNetBuffer.cpp new file mode 100644 index 0000000..57174ab --- /dev/null +++ b/lib/libkiwi/net/kiwiNetBuffer.cpp @@ -0,0 +1,284 @@ +#include + +#include + +namespace kiwi { +namespace detail { + +/****************************************************************************** + * + * CommandBlock + * + ******************************************************************************/ + +/** + * @brief Context for asynchronous socket operations + */ +struct NetBuffer::CommandBlock { + /** + * @brief Command type + */ + enum EType { + EType_None, + EType_Recv, //!< Trying to receive data + EType_Send, //!< Trying to send data + }; + + //! Socket operation that was requested + EType type; + //! Buffer that requested the socket operation + NetBuffer* pBuffer; + + //! Buffer callback provided by the user + Callback pCallback; + //! Buffer callback user argument + void* pArg; + + /** + * @brief Constructor + */ + CommandBlock() + : type(EType_None), + pBuffer(nullptr), + pCallback(nullptr), + pArg(nullptr) {} +}; + +/****************************************************************************** + * + * NetBuffer + * + ******************************************************************************/ + +/** + * @brief Constructor + * + * @param size Buffer size + */ +NetBuffer::NetBuffer(u32 size) { + Init(); + Alloc(size); +} + +/** + * @brief Allocates a network buffer of the specified size + * + * @param size Buffer size + */ +void NetBuffer::Alloc(u32 size) { + K_ASSERT(size > 0); + + // Release existing buffer + Free(); + + // Buffer needs to be in MEM2 so IOS can access it + mpBuffer = new (32, EMemory_MEM2) u8[size]; + K_ASSERT_PTR(mpBuffer); + K_ASSERT(OSIsMEM2Region(mpBuffer)); + + mBufferSize = size; + mReadOffset = mWriteOffset = 0; +} + +/** + * @brief Releases the network buffer + */ +void NetBuffer::Free() { + delete[] mpBuffer; + Init(); +} + +/** + * @brief Expands the existing buffer to at least the specified size + * + * @param size Buffer size + */ +void NetBuffer::Reserve(u32 size) { + K_ASSERT(size > 0); + + if (size < mBufferSize) { + return; + } + + // Buffer needs to be in MEM2 so IOS can access it + u8* pNewBuffer = new (32, EMemory_MEM2) u8[size]; + K_ASSERT_PTR(pNewBuffer); + K_ASSERT(OSIsMEM2Region(pNewBuffer)); + + // Copy existing contents + if (mpBuffer != nullptr) { + std::memcpy(pNewBuffer, mpBuffer, mBufferSize); + delete[] mpBuffer; + } + + mpBuffer = pNewBuffer; + mBufferSize = size; +} + +/** + * @brief Reads data from the network buffer + * + * @param pDst Data destination + * @param size Data size + * + * @return Number of bytes read + */ +u32 NetBuffer::Read(void* pDst, u32 size) { + K_ASSERT_PTR(pDst); + K_ASSERT(size < mBufferSize); + K_ASSERT_PTR(mpBuffer); + + // Don't allow overflow + size = kiwi::Min(size, mBufferSize - mReadOffset); + + std::memcpy(pDst, mpBuffer + mReadOffset, size); + mReadOffset += size; + + return size; +} + +/** + * @brief Writes data to the network buffer + * + * @param pSrc Data source + * @param size Data size + * + * @return Number of bytes written + */ +u32 NetBuffer::Write(const void* pSrc, u32 size) { + K_ASSERT_PTR(pSrc); + K_ASSERT(size < mBufferSize); + K_ASSERT_PTR(mpBuffer); + + // Don't allow overflow + size = kiwi::Min(size, mBufferSize - mWriteOffset); + + std::memcpy(mpBuffer + mWriteOffset, pSrc, size); + mWriteOffset += size; + + return size; +} + +/** + * @brief Receives data into the network buffer + * + * @param pSocket Network socket + * @param[out] pPeerAddr Sender address + * @param pCallback Socket transfer callback + * @param pArg Callback user argument + */ +void NetBuffer::Recv(SocketBase* pSocket, SockAddrAny* pPeerAddr, + Callback pCallback, void* pArg) { + K_ASSERT_PTR(pSocket); + K_ASSERT_PTR(mpBuffer); + + // Context structure to help unwind the callback chain + CommandBlock* pCmdBlock = new CommandBlock(); + K_ASSERT_PTR(pCmdBlock); + + pCmdBlock->type = CommandBlock::EType_Recv; + pCmdBlock->pBuffer = this; + pCmdBlock->pCallback = pCallback; + pCmdBlock->pArg = pArg; + + // Try to complete receiving in one go + K_ASSERT(mWriteOffset >= mReadOffset); + u32 length = Capacity() - (mWriteOffset - mReadOffset); + + if (pPeerAddr != nullptr) { + pSocket->RecvBytesFrom(mpBuffer + mWriteOffset, length, *pPeerAddr, + SocketXferCallback, pCmdBlock); + } else { + pSocket->RecvBytes(mpBuffer + mWriteOffset, length, SocketXferCallback, + pCmdBlock); + } +} + +/** + * @brief Sends data from the network buffer + * + * @param pSocket Network socket + * @param pPeerAddr Receiver address + * @param pCallback Socket transfer callback + * @param pArg Callback user argument + */ +void NetBuffer::Send(SocketBase* pSocket, const SockAddrAny* pPeerAddr, + Callback pCallback, void* pArg) { + K_ASSERT_PTR(pSocket); + K_ASSERT_PTR(mpBuffer); + + // Context structure to help unwind the callback chain + CommandBlock* pCmdBlock = new CommandBlock(); + K_ASSERT_PTR(pCmdBlock); + + pCmdBlock->type = CommandBlock::EType_Send; + pCmdBlock->pBuffer = this; + pCmdBlock->pCallback = pCallback; + pCmdBlock->pArg = pArg; + + // Try to complete sending in one go + u32 length = Size(); + + if (pPeerAddr != nullptr) { + pSocket->SendBytesTo(mpBuffer + mReadOffset, length, *pPeerAddr, + SocketXferCallback, pCmdBlock); + } else { + pSocket->SendBytes(mpBuffer + mReadOffset, length, SocketXferCallback, + pCmdBlock); + } +} + +/** + * @brief Initializes the buffer state + */ +void NetBuffer::Init() { + mpBuffer = nullptr; + mBufferSize = 0; + mReadOffset = mWriteOffset = 0; +} + +/** + * @brief Socket transfer (send/recv) completion callback + * + * @param result Socket library result + * @param size Number of bytes transferred + * @param pArg User callback argument + */ +void NetBuffer::SocketXferCallback(SOResult result, u32 size, void* pArg) { + K_ASSERT_PTR(pArg); + + // Context structure to help unwind the callback chain + CommandBlock* pCmdBlock = static_cast(pArg); + NetBuffer* p = pCmdBlock->pBuffer; + + // Adjust the buffer indices based on which operation happened + switch (pCmdBlock->type) { + case CommandBlock::EType_Recv: { + p->mWriteOffset += size; + K_ASSERT(p->mWriteOffset <= p->mBufferSize); + break; + } + + case CommandBlock::EType_Send: { + p->mReadOffset += size; + K_ASSERT(p->mReadOffset <= p->mBufferSize); + break; + } + + default: { + K_UNREACHABLE(); + break; + } + } + + // Unwind the callback chain + if (pCmdBlock->pCallback != nullptr) { + pCmdBlock->pCallback(result, size, pCmdBlock->pArg); + } + + // Release context memory + delete pCmdBlock; +} + +} // namespace detail +} // namespace kiwi diff --git a/lib/libkiwi/net/kiwiNetBuffer.h b/lib/libkiwi/net/kiwiNetBuffer.h new file mode 100644 index 0000000..97c4fd1 --- /dev/null +++ b/lib/libkiwi/net/kiwiNetBuffer.h @@ -0,0 +1,184 @@ +#ifndef LIBKIWI_NET_NET_BUFFER_H +#define LIBKIWI_NET_NET_BUFFER_H +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ +namespace detail { +//! @addtogroup libkiwi_net +//! @{ + +/** + * @brief Network transfer buffer + */ +class NetBuffer { +public: + /** + * @brief Socket transfer callback + * + * @param result Socket library result + * @param size Transfer size + * @param pArg Callback user argument + */ + typedef void (*Callback)(SOResult result, u32 size, void* pArg); + +public: + /** + * @brief Constructor + */ + NetBuffer() { + Init(); + } + + /** + * @brief Constructor + * + * @param size Buffer size + */ + explicit NetBuffer(u32 size); + + /** + * @brief Destructor + */ + ~NetBuffer() { + Free(); + } + + /** + * @brief Allocates a network buffer of the specified size + * + * @param size Buffer size + */ + void Alloc(u32 size); + + /** + * @brief Releases the network buffer + */ + void Free(); + + /** + * @brief Expands the existing buffer to at least the specified size + * + * @param size Buffer size + */ + void Reserve(u32 size); + + /** + * @brief Reads data from the network buffer + * + * @param pDst Data destination + * @param size Data size + * + * @return Number of bytes read + */ + u32 Read(void* pDst, u32 size); + + /** + * @brief Writes data to the network buffer + * + * @param pSrc Data source + * @param size Data size + * + * @return Number of bytes written + */ + u32 Write(const void* pSrc, u32 size); + + /** + * @brief Receives data into the network buffer + * + * @param pSocket Network socket + * @param[out] pPeerAddr Sender address + * @param pCallback Socket transfer callback + * @param pArg Callback user argument + */ + void Recv(SocketBase* pSocket, SockAddrAny* pPeerAddr, + Callback pCallback = nullptr, void* pArg = nullptr); + + /** + * @brief Sends data from the network buffer + * + * @param pSocket Network socket + * @param pPeerAddr Receiver address + * @param pCallback Socket transfer callback + * @param pArg Callback user argument + */ + void Send(SocketBase* pSocket, const SockAddrAny* pPeerAddr, + Callback pCallback = nullptr, void* pArg = nullptr); + + /** + * @brief Tests whether the underlying buffer is valid + */ + bool IsValid() const { + return mpBuffer != nullptr; + } + + /** + * @brief Accesses the underlying buffer data + */ + u8* Data() { + return mpBuffer; + } + /** + * @brief Accesses the underlying buffer data (const-view) + */ + const u8* Data() const { + return mpBuffer; + } + + /** + * @brief Gets the number of bytes the buffer can hold + */ + u32 Capacity() const { + return mBufferSize; + } + + /** + * @brief Gets the number of bytes available to read + */ + u32 Size() const { + K_ASSERT(mReadOffset <= mWriteOffset); + return mWriteOffset - mReadOffset; + } + +private: + //! Context for asynchronous socket operations + struct CommandBlock; + +private: + /** + * @brief Initializes the buffer state + */ + void Init(); + + /** + * @brief Socket transfer (send/recv) completion callback + * + * @param result Socket library result + * @param size Number of bytes transferred + * @param pArg User callback argument + */ + static void SocketXferCallback(SOResult result, u32 size, void* pArg); + +private: + //! Buffer data + u8* mpBuffer; + //! Buffer size + u32 mBufferSize; + + //! Read position + u32 mReadOffset; + //! Write position + u32 mWriteOffset; +}; + +//! @} +} // namespace detail +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiNetClient.h b/lib/libkiwi/net/kiwiNetClient.h new file mode 100644 index 0000000..110c55f --- /dev/null +++ b/lib/libkiwi/net/kiwiNetClient.h @@ -0,0 +1,28 @@ +#ifndef LIBKIWI_NET_NET_CLIENT_H +#define LIBKIWI_NET_NET_CLIENT_H +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +/** + * @brief Network client + */ +class NetClient : public detail::NetConnection { +public: + /** + * @brief Constructor + * + * @param pSocket Network socket + * @param pPacketFactory Packet factory + */ + NetClient(SocketBase* pSocket, IPacketFactory* pPacketFactory) + : NetConnection(pSocket, pPacketFactory) {} +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiNetConnection.cpp b/lib/libkiwi/net/kiwiNetConnection.cpp new file mode 100644 index 0000000..ea8d0a5 --- /dev/null +++ b/lib/libkiwi/net/kiwiNetConnection.cpp @@ -0,0 +1,113 @@ +#include + +namespace kiwi { +namespace detail { + +/** + * @brief Constructor + * + * @param pSocket Network socket (not owned by the connection!) + * @param pPacketFactory Packet factory + */ +NetConnection::NetConnection(SocketBase* pSocket, + IPacketFactory* pPacketFactory) + : mpSocket(pSocket), + mpPacketFactory(pPacketFactory), + mpRecvPacket(nullptr), + mpRecvCallback(nullptr) { + + K_ASSERT_PTR(mpSocket); + K_ASSERT_PTR(mpPacketFactory); + + NetConnectionMgr::GetInstance().AddConnection(this); +} + +/** + * @brief Destructor + */ +NetConnection::~NetConnection() { + NetConnectionMgr::GetInstance().RemoveConnection(this); + + // Not owned by the connection + mpSocket = nullptr; + + delete mpPacketFactory; + mpPacketFactory = nullptr; + + delete mpRecvPacket; + mpRecvPacket = nullptr; + + // Release memory for outgoing packets + for (TList::Iterator it = mSendPackets.Begin(); + it != mSendPackets.End();) { + + TList::Iterator curr = it++; + delete &*curr; + } +} + +/** + * @brief Sends bytes over the connection + * + * @param pSrc Source buffer + * @param size Buffer size + * @param pPeerAddr Peer address (for datagram connections) + */ +void NetConnection::Send(const void* pSrc, u32 size, + const SockAddrAny* pPeerAddr) { + K_ASSERT_PTR(pSrc); + K_ASSERT(size > 0); + K_ASSERT(pPeerAddr == nullptr || pPeerAddr->IsValid()); + + K_ASSERT_PTR(mpPacketFactory); + PacketBase* pSendPacket = mpPacketFactory->Create(pPeerAddr); + + K_ASSERT_PTR(pSendPacket); + pSendPacket->Alloc(size); + pSendPacket->SetContent(pSrc, size); + + K_ASSERT_PTR(mpSocket); + pSendPacket->Send(mpSocket); + + mSendPackets.PushBack(pSendPacket); +} + +/** + * @brief Updates the connection state + */ +void NetConnection::Calc() { + K_ASSERT_PTR(mpSocket); + + // Packets will not be received until a callback is registered + if (mpRecvCallback != nullptr) { + // Always maintain one receive packet + if (mpRecvPacket == nullptr) { + K_ASSERT_PTR(mpPacketFactory); + mpRecvPacket = mpPacketFactory->Create(); + + K_ASSERT_PTR(mpRecvPacket); + mpRecvPacket->Recv(mpSocket); + } + + // Update receive operation + if (mpRecvPacket->Calc()) { + mpRecvCallback(mpRecvPacket, mpRecvCallbackArg); + + delete mpRecvPacket; + mpRecvPacket = nullptr; + } + } + + // Update next send operation + if (!mSendPackets.Empty()) { + PacketBase& rSendPacket = *mSendPackets.Front(); + + if (rSendPacket.Calc()) { + mSendPackets.PopFront(); + delete &rSendPacket; + } + } +} + +} // namespace detail +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/net/kiwiNetConnection.h b/lib/libkiwi/net/kiwiNetConnection.h new file mode 100644 index 0000000..6d95790 --- /dev/null +++ b/lib/libkiwi/net/kiwiNetConnection.h @@ -0,0 +1,137 @@ +#ifndef LIBKIWI_NET_NET_CONNECTION_H +#define LIBKIWI_NET_NET_CONNECTION_H +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class IPacketFactory; +class PacketBase; +class SockAddrAny; +class SocketBase; + +namespace detail { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class NetConnectionMgr; + +/** + * @brief Network socket connection wrapper + */ +class NetConnection { + // Expose Calc only to the manager + friend class NetConnectionMgr; + +public: + /** + * @brief Packet receive callback + * + * @param pPacket Incoming packet + * @param pArg Callback user argument + */ + typedef void (*RecvCallback)(PacketBase* pPacket, void* pArg); + +public: + /** + * @brief Constructor + * + * @param pSocket Network socket (not owned by the connection!) + * @param pPacketFactory Packet factory + */ + NetConnection(SocketBase* pSocket, IPacketFactory* pPacketFactory); + + /** + * @brief Destructor + */ + virtual ~NetConnection(); + + /** + * @brief Binds socket to local address + * @note Bind to port zero for a random port (written out) + * + * @param rAddr[in,out] Local address + * @return Success + */ + bool Bind(SockAddrAny& rAddr) { + K_ASSERT_PTR(mpSocket); + return mpSocket->Bind(rAddr); + } + + /** + * @brief Sends bytes over the connection + * + * @param pSrc Source buffer + * @param size Buffer size + * @param pPeerAddr Peer address (for datagram connections) + */ + void Send(const void* pSrc, u32 size, + const SockAddrAny* pPeerAddr = nullptr); + + /** + * @brief Sends an object over the connection + * + * @tparam T Object type + * @param rSrc Source object + * @param pPeerAddr Peer address (for datagram connections) + */ + template + void Send(const T& rSrc, const SockAddrAny* pPeerAddr = nullptr) { + Send(&rSrc, sizeof(T), pPeerAddr); + } + + /** + * @brief Sets the packet factory used for this connection + * + * @param pPacketFactory New packet factory + */ + void SetPacketFactory(IPacketFactory* pPacketFactory) { + K_ASSERT_PTR(pPacketFactory); + mpPacketFactory = pPacketFactory; + } + + /** + * @brief Sets the callback used to handle incoming packets + * + * @param pCallback Packet receive callback + * @param pArg Callback user argument + */ + void SetRecvCallback(RecvCallback pCallback, void* pArg = nullptr) { + K_ASSERT_PTR(pCallback); + mpRecvCallback = pCallback; + mpRecvCallbackArg = pArg; + } + +protected: + //! Network socket (not owning!) + SocketBase* mpSocket; + //! Packet factory + IPacketFactory* mpPacketFactory; + + //! Incoming packet + PacketBase* mpRecvPacket; + //! Outgoing packets + TList mSendPackets; + + //! Incoming packet callback + RecvCallback mpRecvCallback; + //! Callback user argument + void* mpRecvCallbackArg; + +private: + /** + * @brief Updates the connection state + */ + void Calc(); +}; + +//! @} +} // namespace detail +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiNetConnectionMgr.cpp b/lib/libkiwi/net/kiwiNetConnectionMgr.cpp new file mode 100644 index 0000000..4e88bae --- /dev/null +++ b/lib/libkiwi/net/kiwiNetConnectionMgr.cpp @@ -0,0 +1,33 @@ +#include + +namespace kiwi { +namespace detail { + +/** + * @brief Constructor + */ +NetConnectionMgr::NetConnectionMgr() { + mpThread = new StdThread(&NetConnectionMgr::ThreadFunc, *this); +} + +/** + * @brief Destructor + */ +NetConnectionMgr::~NetConnectionMgr() { + delete mpThread; + mpThread = nullptr; +} + +/** + * @brief Thread function + */ +void NetConnectionMgr::ThreadFunc() { + while (true) { + K_FOREACH (it, mConnectionList) { + (*it)->Calc(); + } + } +} + +} // namespace detail +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/net/kiwiNetConnectionMgr.h b/lib/libkiwi/net/kiwiNetConnectionMgr.h new file mode 100644 index 0000000..efcdff1 --- /dev/null +++ b/lib/libkiwi/net/kiwiNetConnectionMgr.h @@ -0,0 +1,75 @@ +#ifndef LIBKIWI_NET_NET_CONNECTION_MGR_H +#define LIBKIWI_NET_NET_CONNECTION_MGR_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class StdThread; + +namespace detail { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class NetConnection; + +/** + * @brief Network socket connection manager + */ +class NetConnectionMgr : public StaticSingleton { + friend class StaticSingleton; + +public: + /** + * @brief Appends a new network connection to the manager list + * + * @param pConnection New network connection + */ + void AddConnection(NetConnection* pConnection) { + K_ASSERT_PTR(pConnection); + mConnectionList.PushBack(pConnection); + } + + /** + * @brief Removes a network connection from the manager list + * + * @param pConnection Network connection + */ + void RemoveConnection(NetConnection* pConnection) { + mConnectionList.Remove(pConnection); + } + +private: + /** + * @brief Constructor + */ + NetConnectionMgr(); + + /** + * @brief Destructor + */ + ~NetConnectionMgr(); + + /** + * @brief Thread function + */ + void ThreadFunc(); + +private: + //! Manager thread + StdThread* mpThread; + //! Open connections + TList mConnectionList; +}; + +//! @} +} // namespace detail +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiNetServer.h b/lib/libkiwi/net/kiwiNetServer.h new file mode 100644 index 0000000..486db54 --- /dev/null +++ b/lib/libkiwi/net/kiwiNetServer.h @@ -0,0 +1,28 @@ +#ifndef LIBKIWI_NET_NET_SERVER_H +#define LIBKIWI_NET_NET_SERVER_H +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +/** + * @brief Network server + */ +class NetServer : public detail::NetConnection { +public: + /** + * @brief Constructor + * + * @param pSocket Network socket + * @param pPacketFactory Packet factory + */ + NetServer(SocketBase* pSocket, IPacketFactory* pPacketFactory) + : NetConnection(pSocket, pPacketFactory) {} +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/kiwiPacket.cpp b/lib/libkiwi/net/kiwiPacket.cpp deleted file mode 100644 index daf8531..0000000 --- a/lib/libkiwi/net/kiwiPacket.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include - -namespace kiwi { - -/** - * @brief Allocates message buffer of the specified size - * - * @param size Packet size - */ -void Packet::Alloc(u32 size) { - K_ASSERT(size > 0); - K_ASSERT_EX(size < GetMaxContent(), "Must be fragmented!"); - - // Free existing message - if (mpBuffer != nullptr) { - Free(); - } - - // Protocol may have memory overhead - mBufferSize = size + GetOverhead(); - - mpBuffer = new (32, EMemory_MEM2) u8[mBufferSize]; - K_ASSERT_PTR(mpBuffer); - K_ASSERT(OSIsMEM2Region(mpBuffer)); - - Clear(); -} - -/** - * @brief Releases message buffer - */ -void Packet::Free() { - AutoMutexLock lock(mBufferMutex); - - delete mpBuffer; - mpBuffer = nullptr; - - Clear(); -} - -/** - * @brief Clears existing state - */ -void Packet::Clear() { - AutoMutexLock lock(mBufferMutex); - - mReadOffset = 0; - mWriteOffset = 0; -} - -/** - * @brief Reads data from message buffer - * - * @param pDst Data destination - * @param size Data size - * - * @return Number of bytes read - */ -u32 Packet::Read(void* pDst, u32 size) { - K_ASSERT_PTR(mpBuffer); - K_ASSERT(size <= GetMaxContent()); - - AutoMutexLock lock(mBufferMutex); - - // Clamp size to avoid overflow - size = Min(size, ReadRemain()); - - // Copy data from buffer - std::memcpy(pDst, mpBuffer + mReadOffset, size); - mReadOffset += size; - - return size; -} - -/** - * @brief Writes data to message buffer - * - * @param pSrc Data source - * @param size Data size - * - * @return Number of bytes written - */ -u32 Packet::Write(const void* pSrc, u32 size) { - K_ASSERT_PTR(mpBuffer); - K_ASSERT(size <= GetMaxContent()); - - AutoMutexLock lock(mBufferMutex); - - // Clamp size to avoid overflow - size = Min(size, WriteRemain()); - - // Copy data to buffer - std::memcpy(mpBuffer + mWriteOffset, pSrc, size); - mWriteOffset += size; - - return size; -} - -/** - * @brief Receives message data from socket - * - * @param socket Socket descriptor - * - * @return Number of bytes received - */ -Optional Packet::Recv(SOSocket socket) { - K_ASSERT(socket >= 0); - K_ASSERT_PTR(mpBuffer); - - AutoMutexLock lock(mBufferMutex); - - // Read from socket (try to complete packet) - s32 result = LibSO::RecvFrom(socket, mpBuffer + mWriteOffset, WriteRemain(), - 0, mAddress); - - // Blocking, just say zero - if (result == SO_EWOULDBLOCK) { - return 0; - } - - // > 0 means bytes read from socket - if (result >= 0) { - mWriteOffset += result; - return result; - } - - return kiwi::nullopt; -} - -/** - * @brief Writes message data to socket - * - * @param socket Socket descriptor - * - * @return Number of bytes sent - */ -Optional Packet::Send(SOSocket socket) { - K_ASSERT(socket >= 0); - K_ASSERT_PTR(mpBuffer); - - AutoMutexLock lock(mBufferMutex); - - // Send through socket (try to complete packet) - s32 result = LibSO::SendTo(socket, mpBuffer + mReadOffset, ReadRemain(), 0, - mAddress); - - // Blocking, just say zero - if (result == SO_EWOULDBLOCK) { - return 0; - } - - // > 0 means bytes written to socket - if (result >= 0) { - mReadOffset += result; - return result; - } - - return kiwi::nullopt; -} - -} // namespace kiwi diff --git a/lib/libkiwi/net/kiwiPacket.h b/lib/libkiwi/net/kiwiPacket.h deleted file mode 100644 index 6e90ad3..0000000 --- a/lib/libkiwi/net/kiwiPacket.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef LIBKIWI_NET_PACKET_H -#define LIBKIWI_NET_PACKET_H -#include -#include -#include -#include -#include - -#include - -#include - -namespace kiwi { -//! @addtogroup libkiwi_net -//! @{ - -/** - * @brief Network packet wrapper - */ -class Packet { -public: - /** - * @brief Constructor - * - * @param size Packet buffer size - * @param pAddr Packet recipient - */ - Packet(u32 size, const SockAddrAny* pAddr = nullptr) - : mpBuffer(nullptr), mBufferSize(0), mReadOffset(0), mWriteOffset(0) { - - Alloc(size); - - if (pAddr != nullptr) { - mAddress = *pAddr; - } else { - mAddress = SockAddr4(); - } - } - - /** - * @brief Destructor - */ - ~Packet() { - Free(); - } - - /** - * @brief Gets the current size of the message buffer - */ - virtual u32 GetBufferSize() const { - return mBufferSize; - } - /** - * @brief Gets the maximum size of the message buffer - */ - virtual u32 GetMaxBuffer() const { - return ULONG_MAX; - } - - /** - * @brief Gets the current size of the message payload - */ - virtual u32 GetContentSize() const { - return GetBufferSize() - GetOverhead(); - } - /** - * @brief Gets the maximum size of the message payload - */ - virtual u32 GetMaxContent() const { - return GetMaxBuffer() - GetOverhead(); - } - /** - * @brief Accesses the message payload - */ - const void* GetContent() const { - return mpBuffer + GetOverhead(); - } - - /** - * @brief Gets the size of the message buffer overhead - */ - virtual u32 GetOverhead() const { - return 0; - } - - /** - * @brief Tests whether the packet contains no data - */ - bool IsEmpty() const { - return mpBuffer == nullptr || GetContentSize() == 0; - } - - /** - * @brief Gets the number of bytes that must be read to complete the packet - */ - u32 ReadRemain() const { - return Max(GetContentSize() - mReadOffset, 0); - } - /** - * @brief Gets the number of bytes that must be written to complete the - * packet - */ - u32 WriteRemain() const { - return Max(GetContentSize() - mWriteOffset, 0); - } - - /** - * @brief Tests whether read operation has been completed - */ - bool IsReadComplete() const { - return ReadRemain() == 0; - } - /** - * @brief Tests whether write operation has been completed - */ - bool IsWriteComplete() const { - return WriteRemain() == 0; - } - - /** - * @brief Accesses peer socket address (read-only) - */ - const SockAddrAny& GetPeer() const { - return mAddress; - } - - /** - * @brief Allocates message buffer of the specified size - * - * @param size Packet size - */ - void Alloc(u32 size); - - /** - * @brief Reads data from message buffer - * - * @param pDst Data destination - * @param size Data size - * - * @return Number of bytes read - */ - u32 Read(void* pDst, u32 size); - /** - * @brief Writes data to message buffer - * - * @param pSrc Data source - * @param size Data size - * - * @return Number of bytes written - */ - u32 Write(const void* pSrc, u32 size); - - /** - * @brief Receives message data from socket - * - * @param socket Socket descriptor - * - * @return Number of bytes received - */ - Optional Send(SOSocket socket); - /** - * @brief Writes message data to socket - * - * @param socket Socket descriptor - * - * @return Number of bytes sent - */ - Optional Recv(SOSocket socket); - -protected: - /** - * @brief Releases message buffer - */ - void Free(); - - /** - * @brief Clears existing state - */ - void Clear(); - -protected: - u8* mpBuffer; //!< Message buffer - u32 mBufferSize; //!< Message buffer size - Mutex mBufferMutex; //!< Buffer access mutex - - s32 mReadOffset; //!< Buffer read index - s32 mWriteOffset; //!< Buffer write index - - SockAddrAny mAddress; //!< Sender (recv) or recipient (send) -}; - -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/net/kiwiReliableClient.cpp b/lib/libkiwi/net/kiwiReliableClient.cpp deleted file mode 100644 index d75c94d..0000000 --- a/lib/libkiwi/net/kiwiReliableClient.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -namespace kiwi { - -; - -} // namespace kiwi diff --git a/lib/libkiwi/net/kiwiReliableClient.h b/lib/libkiwi/net/kiwiReliableClient.h deleted file mode 100644 index 9629bdf..0000000 --- a/lib/libkiwi/net/kiwiReliableClient.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef LIBKIWI_NET_RELIABLE_CLIENT_H -#define LIBKIWI_NET_RELIABLE_CLIENT_H -#include - -namespace kiwi { -//! @addtogroup libkiwi_net -//! @{ - -class ReliableClient {}; - -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/net/kiwiReliablePacket.h b/lib/libkiwi/net/kiwiReliablePacket.h deleted file mode 100644 index a714a76..0000000 --- a/lib/libkiwi/net/kiwiReliablePacket.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef LIBKIWI_NET_RELIABLE_PACKET_H -#define LIBKIWI_NET_RELIABLE_PACKET_H -#include -#include -#include - -namespace kiwi { -//! @addtogroup libkiwi_net -//! @{ - -/** - * @brief Reliable packet header - * @note Concepts adapted from NEX PRUDP - */ -struct KUDPHeader { - /** - * @brief Constructor - */ - KUDPHeader() - : magic(SIGNATURE), size(0), sequence(0), fragment(0), flags(0) {} - - /* 0x00 */ u32 magic; //!< Identification - /* 0x04 */ u16 size; //!< Message size - /* 0x06 */ u16 sequence; //!< Sequence ID - /* 0x08 */ u16 fragment; //!< Fragment ID - /* 0x0A */ u16 flags; //!< Status/info - - //! Identifier string - static const u32 SIGNATURE = 'KUv0'; - - /** - * @brief Packet flags - */ - enum EFlags { - //! This packet is only a message fragment, and there will be more - EFlags_MoreFragments = (1 << 0), - }; -}; - -/** - * @brief Reliable UDP protocol (KUDP) packet - */ -class ReliablePacket : public Packet { -public: - //! Message buffer limit to stay under MTU - static const u16 MAX_BUFFER_SIZE = 1000; - //! Message content limit - static const u16 MAX_CONTENT_SIZE = MAX_BUFFER_SIZE - sizeof(KUDPHeader); - -public: - /** - * @brief Constructor - * - * @param size Packet buffer size - * @param pAddr Packet recipient - */ - ReliablePacket(u32 size, const SockAddrAny* pAddr = nullptr) - : Packet(size, pAddr) {} - - /** - * @brief Accesses KUDP protocol header - */ - KUDPHeader& GetHeader() { - K_ASSERT_PTR(mpBuffer); - return *reinterpret_cast(mpBuffer); - } - /** - * @brief Accesses KUDP protocol header (read-only) - */ - const KUDPHeader& GetHeader() const { - K_ASSERT_PTR(mpBuffer); - return *reinterpret_cast(mpBuffer); - } - - /** - * @brief Gets the maximum size of the message buffer - */ - virtual u32 GetMaxBuffer() const { - return MAX_BUFFER_SIZE; - } - - /** - * @brief Gets the current size of the message payload - */ - virtual u32 GetContentSize() const { - return GetHeader().size; - } - /** - * @brief Gets the maximum size of the message payload - */ - virtual u32 GetMaxContent() const { - return MAX_CONTENT_SIZE; - } - - /** - * @brief Gets the size of the message buffer overhead - */ - virtual u32 GetOverhead() const { - return sizeof(KUDPHeader); - } -}; - -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/net/kiwiReliableSocket.cpp b/lib/libkiwi/net/kiwiReliableSocket.cpp deleted file mode 100644 index d75c94d..0000000 --- a/lib/libkiwi/net/kiwiReliableSocket.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include - -namespace kiwi { - -; - -} // namespace kiwi diff --git a/lib/libkiwi/net/kiwiReliableSocket.h b/lib/libkiwi/net/kiwiReliableSocket.h deleted file mode 100644 index a13b2a2..0000000 --- a/lib/libkiwi/net/kiwiReliableSocket.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef LIBKIWI_NET_RELIABLE_SOCKET_H -#define LIBKIWI_NET_RELIABLE_SOCKET_H -#include -#include - -namespace kiwi { -//! @addtogroup libkiwi_net -//! @{ - -class ReliableSocket : public AsyncSocket {}; - -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/net/kiwiSocketBase.cpp b/lib/libkiwi/net/kiwiSocketBase.cpp index 65ad4d7..38a5df1 100644 --- a/lib/libkiwi/net/kiwiSocketBase.cpp +++ b/lib/libkiwi/net/kiwiSocketBase.cpp @@ -23,6 +23,11 @@ SocketBase::SocketBase(SOProtoFamily family, SOSockType type) // Always disable IOP blocking success = SetBlockingIOP(false); K_ASSERT(success); + + success = SetSendBufferSize(0xFFFF); + K_ASSERT(success); + success = SetRecvBufferSize(0xFFFF); + K_ASSERT(success); } /** @@ -231,7 +236,7 @@ bool SocketBase::CanSend() const { * @param pArg Callback user argument * @return Number of bytes received */ -Optional SocketBase::RecvBytes(void* pDst, u32 len, Callback pCallback, +Optional SocketBase::RecvBytes(void* pDst, u32 len, XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pDst); @@ -260,7 +265,7 @@ Optional SocketBase::RecvBytes(void* pDst, u32 len, Callback pCallback, * @return Number of bytes received */ Optional SocketBase::RecvBytesFrom(void* pDst, u32 len, SockAddrAny& rAddr, - Callback pCallback, void* pArg) { + XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pDst); K_ASSERT(OSIsMEM2Region(pDst)); @@ -287,7 +292,7 @@ Optional SocketBase::RecvBytesFrom(void* pDst, u32 len, SockAddrAny& rAddr, * @return Number of bytes sent */ Optional SocketBase::SendBytes(const void* pSrc, u32 len, - Callback pCallback, void* pArg) { + XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pSrc); K_ASSERT(OSIsMEM2Region(pSrc)); @@ -316,7 +321,7 @@ Optional SocketBase::SendBytes(const void* pSrc, u32 len, */ Optional SocketBase::SendBytesTo(const void* pSrc, u32 len, const SockAddrAny& rAddr, - Callback pCallback, void* pArg) { + XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pSrc); K_ASSERT(OSIsMEM2Region(pSrc)); diff --git a/lib/libkiwi/net/kiwiSocketBase.h b/lib/libkiwi/net/kiwiSocketBase.h index 00dbd99..1c98962 100644 --- a/lib/libkiwi/net/kiwiSocketBase.h +++ b/lib/libkiwi/net/kiwiSocketBase.h @@ -14,23 +14,32 @@ namespace kiwi { class SocketBase : private NonCopyable { public: /** - * @brief Generic socket operation callback + * @brief Acceptance completion callback * * @param result Socket library result + * @param pPeer Peer socket object + * @param rAddr Peer address * @param pArg User callback argument */ - typedef void (*Callback)(SOResult result, void* pArg); + typedef void (*AcceptCallback)(SOResult result, SocketBase* pPeer, + const SockAddrAny& rAddr, void* pArg); /** - * @brief Connection accept callback + * @brief Connection completion callback * * @param result Socket library result - * @param pPeer Peer socket object - * @param rAddr Peer address * @param pArg User callback argument */ - typedef void (*AcceptCallback)(SOResult result, SocketBase* pPeer, - const SockAddrAny& rAddr, void* pArg); + typedef void (*ConnectCallback)(SOResult result, void* pArg); + + /** + * @brief Socket transfer (send/recv) completion callback + * + * @param result Socket library result + * @param size Number of bytes transferred + * @param pArg User callback argument + */ + typedef void (*XferCallback)(SOResult result, u32 size, void* pArg); public: /** @@ -68,7 +77,8 @@ class SocketBase : private NonCopyable { * @param pArg Callback user argument * @return Success */ - virtual bool Connect(const SockAddrAny& rAddr, Callback pCallback = nullptr, + virtual bool Connect(const SockAddrAny& rAddr, + ConnectCallback pCallback = nullptr, void* pArg = nullptr) = 0; /** @@ -173,7 +183,8 @@ class SocketBase : private NonCopyable { * @param pArg Callback user argument * @return Number of bytes received */ - Optional RecvBytes(void* pDst, u32 len, Callback pCallback = nullptr, + Optional RecvBytes(void* pDst, u32 len, + XferCallback pCallback = nullptr, void* pArg = nullptr); /** * @brief Receives bytes and records sender address @@ -186,7 +197,7 @@ class SocketBase : private NonCopyable { * @return Number of bytes received */ Optional RecvBytesFrom(void* pDst, u32 len, SockAddrAny& rAddr, - Callback pCallback = nullptr, + XferCallback pCallback = nullptr, void* pArg = nullptr); /** @@ -198,7 +209,7 @@ class SocketBase : private NonCopyable { * @return Number of bytes received */ template - Optional Recv(T& rDst, Callback pCallback = nullptr, + Optional Recv(T& rDst, XferCallback pCallback = nullptr, void* pArg = nullptr) { return RecvBytes(&rDst, sizeof(T), pCallback, pArg); } @@ -213,7 +224,8 @@ class SocketBase : private NonCopyable { */ template Optional RecvFrom(T& rDst, SockAddrAny& rAddr, - Callback pCallback = nullptr, void* pArg = nullptr) { + XferCallback pCallback = nullptr, + void* pArg = nullptr) { return RecvBytesFrom(&rDst, sizeof(T), rAddr, pCallback, pArg); } /**@}*/ @@ -232,7 +244,8 @@ class SocketBase : private NonCopyable { * @return Number of bytes sent */ Optional SendBytes(const void* pSrc, u32 len, - Callback pCallback = nullptr, void* pArg = nullptr); + XferCallback pCallback = nullptr, + void* pArg = nullptr); /** * @brief Sends bytes to specified connection * @@ -245,7 +258,7 @@ class SocketBase : private NonCopyable { */ Optional SendBytesTo(const void* pSrc, u32 len, const SockAddrAny& rAddr, - Callback pCallback = nullptr, + XferCallback pCallback = nullptr, void* pArg = nullptr); /** @@ -257,7 +270,7 @@ class SocketBase : private NonCopyable { * @return Number of bytes sent */ template - Optional Send(const T& rSrc, Callback pCallback = nullptr, + Optional Send(const T& rSrc, XferCallback pCallback = nullptr, void* pArg = nullptr) { return SendBytes(&rSrc, sizeof(T), pCallback, pArg); } @@ -272,7 +285,8 @@ class SocketBase : private NonCopyable { */ template Optional SendTo(const T& rSrc, const SockAddrAny& rAddr, - Callback pCallback = nullptr, void* pArg = nullptr) { + XferCallback pCallback = nullptr, + void* pArg = nullptr) { return SendBytesTo(&rSrc, sizeof(T), rAddr, pCallback, pArg); } @@ -285,8 +299,8 @@ class SocketBase : private NonCopyable { * @return Number of bytes sent */ template - Optional Send(const StringImpl& rSrc, Callback pCallback = nullptr, - void* pArg = nullptr) { + Optional Send(const StringImpl& rSrc, + XferCallback pCallback = nullptr, void* pArg = nullptr) { return SendBytes(rSrc.CStr(), rSrc.Length() * sizeof(T), pCallback, pArg); } @@ -301,7 +315,8 @@ class SocketBase : private NonCopyable { */ template Optional SendTo(const StringImpl& rSrc, const SockAddrAny& rAddr, - Callback pCallback = nullptr, void* pArg = nullptr) { + XferCallback pCallback = nullptr, + void* pArg = nullptr) { return SendBytesTo(rSrc.CStr(), rSrc.Length() * sizeof(T), rAddr, pCallback, pArg); } @@ -342,7 +357,7 @@ class SocketBase : private NonCopyable { * @return Socket library result */ virtual SOResult RecvImpl(void* pDst, u32 len, u32& rRecv, - SockAddrAny* pAddr, Callback pCallback, + SockAddrAny* pAddr, XferCallback pCallback, void* pArg) = 0; /** @@ -357,7 +372,7 @@ class SocketBase : private NonCopyable { * @return Socket library result */ virtual SOResult SendImpl(const void* pSrc, u32 len, u32& rSend, - const SockAddrAny* pAddr, Callback pCallback, + const SockAddrAny* pAddr, XferCallback pCallback, void* pArg) = 0; protected: diff --git a/lib/libkiwi/net/kiwiSyncSocket.cpp b/lib/libkiwi/net/kiwiSyncSocket.cpp index 33b54f0..75f0d37 100644 --- a/lib/libkiwi/net/kiwiSyncSocket.cpp +++ b/lib/libkiwi/net/kiwiSyncSocket.cpp @@ -10,7 +10,7 @@ namespace kiwi { * @param pArg Callback user argument * @return Success */ -bool SyncSocket::Connect(const SockAddrAny& rAddr, Callback pCallback, +bool SyncSocket::Connect(const SockAddrAny& rAddr, ConnectCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); @@ -41,7 +41,7 @@ SyncSocket* SyncSocket::Accept(AcceptCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); while (true) { - // TODO: Will forcing ipv4 cause problems? + // TODO(kiwi) Will forcing ipv4 cause problems? SyncSocket* pPeer = nullptr; SockAddr4 addr; @@ -77,7 +77,7 @@ SyncSocket* SyncSocket::Accept(AcceptCallback pCallback, void* pArg) { * @return Socket library result */ SOResult SyncSocket::RecvImpl(void* pDst, u32 len, u32& rRecv, - SockAddrAny* pAddr, Callback pCallback, + SockAddrAny* pAddr, XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pDst); @@ -103,7 +103,7 @@ SOResult SyncSocket::RecvImpl(void* pDst, u32 len, u32& rRecv, } if (pCallback != nullptr) { - pCallback(LibSO::GetLastError(), pArg); + pCallback(LibSO::GetLastError(), rRecv, pArg); } // Successful if some amount of bytes read @@ -123,7 +123,7 @@ SOResult SyncSocket::RecvImpl(void* pDst, u32 len, u32& rRecv, * @return Socket library result */ SOResult SyncSocket::SendImpl(const void* pSrc, u32 len, u32& rSend, - const SockAddrAny* pAddr, Callback pCallback, + const SockAddrAny* pAddr, XferCallback pCallback, void* pArg) { K_ASSERT(IsOpen()); K_ASSERT_PTR(pSrc); @@ -151,7 +151,7 @@ SOResult SyncSocket::SendImpl(const void* pSrc, u32 len, u32& rSend, } if (pCallback != nullptr) { - pCallback(LibSO::GetLastError(), pArg); + pCallback(LibSO::GetLastError(), rSend, pArg); } // Successful if some amount of bytes sent diff --git a/lib/libkiwi/net/kiwiSyncSocket.h b/lib/libkiwi/net/kiwiSyncSocket.h index 9e54cef..b95d1ea 100644 --- a/lib/libkiwi/net/kiwiSyncSocket.h +++ b/lib/libkiwi/net/kiwiSyncSocket.h @@ -21,6 +21,16 @@ class SyncSocket : public SocketBase { SyncSocket(SOProtoFamily family, SOSockType type) : SocketBase(family, type), mIsBlocking(true) {} + /** + * @brief Constructor + * + * @param socket Socket descriptor + * @param family Socket protocol family + * @param type Socket type + */ + SyncSocket(SOSocket socket, SOProtoFamily family, SOSockType type) + : SocketBase(socket, family, type) {} + /** * @brief Connects to a peer * @@ -29,7 +39,8 @@ class SyncSocket : public SocketBase { * @param pArg Callback user argument * @return Success */ - virtual bool Connect(const SockAddrAny& rAddr, Callback pCallback = nullptr, + virtual bool Connect(const SockAddrAny& rAddr, + ConnectCallback pCallback = nullptr, void* pArg = nullptr); /** @@ -58,16 +69,6 @@ class SyncSocket : public SocketBase { } private: - /** - * @brief Constructor - * - * @param socket Socket descriptor - * @param family Socket protocol family - * @param type Socket type - */ - SyncSocket(SOSocket socket, SOProtoFamily family, SOSockType type) - : SocketBase(socket, family, type) {} - /** * @brief Receives data and records sender address (internal implementation) * @@ -80,7 +81,7 @@ class SyncSocket : public SocketBase { * @return Socket library result */ virtual SOResult RecvImpl(void* pDst, u32 len, u32& rRecv, - SockAddrAny* pAddr, Callback pCallback, + SockAddrAny* pAddr, XferCallback pCallback, void* pArg); /** @@ -95,7 +96,7 @@ class SyncSocket : public SocketBase { * @return Socket library result */ virtual SOResult SendImpl(const void* pSrc, u32 len, u32& rSend, - const SockAddrAny* pAddr, Callback pCallback, + const SockAddrAny* pAddr, XferCallback pCallback, void* pArg); private: diff --git a/lib/libkiwi/net/kiwiWebSocket.cpp b/lib/libkiwi/net/kiwiWebSocket.cpp deleted file mode 100644 index f659503..0000000 --- a/lib/libkiwi/net/kiwiWebSocket.cpp +++ /dev/null @@ -1,244 +0,0 @@ -#include - -namespace kiwi { -namespace { - -/** - * @brief Frame opcode - */ -enum EOpcode { - EOpcode_Continuation, //!< Intermediate frame of a fragmented message - EOpcode_Text, //!< UTF-8 encoded application text - EOpcode_Binary, //!< Application binary data - EOpcode_Close = 8, //!< Close frame - EOpcode_Ping, //!< Heartbeat/latency (first) - EOpcode_Pong, //!< Heartbeat/latency (second) -}; - -/** - * @brief Data frame - */ -struct Frame { - /* 0x00:0 */ u8 fin : 1; //!< Final frame of a message - /* 0x00:1 */ u8 rsv1 : 1; //!< Reserved, must be zero - /* 0x00:2 */ u8 rsv2 : 1; //!< Reserved, must be zero - /* 0x00:3 */ u8 rsv3 : 1; //!< Reserved, must be zero - /* 0x00:4 */ u8 opcode : 4; //!< Frame opcode - /* 0x01:0 */ u8 mask : 1; //!< Frame is masked (and masking key is present) - /* 0x01:1 */ u8 length : 7; //!< Payload length - - union { - //! Length is 7 + the following 16 bits - union { - struct { - u16 length; - u8 payload[1]; - } unmasked; - - struct { - u16 length; - u32 masking; - u8 payload[1]; - } masked; - } len16; - - //! Length is 7 + the following 64 bits - union { - struct { - u64 length; - u8 payload[1]; - } unmasked; - - struct { - u64 length; - u32 masking; - u8 payload[1]; - } masked; - } len64; - - union { - struct { - u8 payload[1]; - } unmasked; - - struct { - u32 masking; - u8 payload[1]; - } masked; - }; - }; -}; - -/** - * @brief Websocket protocol version - */ -static const int WEBSOCKET_VERSION = 13; - -/** - * @brief Server accept key constant - */ -static const char* WEBSOCKET_KEY_CONST = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; - -/** - * @brief Generates a random 16-byte key for the WebSocket protocol - */ -String GenerateKey() { - Random r; - u8 key[16]; - - for (int i = 0; i < K_LENGTHOF(key); i++) { - key[i] = static_cast(r.NextU32()); - } - - return B64Encode(key, K_LENGTHOF(key)); -} - -/** - * @brief Generates the expected 'Sec-WebSocket-Accept' value from the given key - * - * @param rKey Key ('Sec-WebSocket-Key') - */ -String GenerateAccept(const String& rKey) { - String expected = rKey + WEBSOCKET_KEY_CONST; - expected = SHA1Hash(expected, expected.Length()); - expected = B64Encode(expected, expected.Length()); - return expected; -} - -} // namespace - -/** - * @brief Constructor - */ -WebSocket::WebSocket() - : mState(EState_None), - mpRequest(nullptr), - mpConnectCallback(nullptr), - mpConnectCallbackArg(nullptr), - mpMessageCallback(nullptr), - mpMessageCallbackArg(nullptr) {} - -/** - * @brief Destructor - */ -WebSocket::~WebSocket() { - delete mpRequest; - mpRequest = nullptr; -} - -/** - * @brief Connects to the specified server hostname - * - * @param rHost Server hostname - * @param pCallback Connection callback - * @param pArg Callback user argument - */ -void WebSocket::Connect(const String& rHost, Callback pCallback, void* pArg) { - // Close existing connection - if (mpRequest != nullptr) { - delete mpRequest; - } - - mpRequest = new HttpRequest(rHost); - K_ASSERT_PTR(mpRequest); - - K_LOG("Connecting...\n"); - - mState = EState_Connecting; - mpConnectCallback = pCallback; - mpConnectCallbackArg = pArg; - - mpRequest->SetHeaderField("Connection", "Upgrade"); - mpRequest->SetHeaderField("Upgrade", "websocket"); - mpRequest->SetHeaderField("Sec-WebSocket-Version", WEBSOCKET_VERSION); - mpRequest->SetHeaderField("Sec-WebSocket-Key", GenerateKey()); - - mpRequest->SendAsync(RequestCallback, this); -} - -/** - * @brief Request response callback - * - * @param rResp Request response - * @param pArg Callback user argument - */ -void WebSocket::RequestCallback(const HttpResponse& rResp, void* pArg) { - K_ASSERT_PTR(pArg); - - // User argument is this object - WebSocket* p = static_cast(pArg); - K_ASSERT_PTR(p->mpRequest); - - // Validate upgrade-related fields - if (rResp.error != EHttpErr_Success || - rResp.status != EHttpStatus_SwitchProto || - rResp.header.Get("Connection") != "Upgrade" || - rResp.header.Get("Upgrade") != "websocket") { - - if (p->mpConnectCallback != nullptr) { - p->mpConnectCallback(EResult_CantUpgrade, p->mpConnectCallbackArg); - } - - p->mState = EState_None; - return; - } - - // Validate server secret - if (rResp.header.Get("Sec-WebSocket-Accept") != - GenerateAccept(*p->mpRequest->GetHeaderField("Sec-WebSocket-Key"))) { - - if (p->mpConnectCallback != nullptr) { - p->mpConnectCallback(EResult_CantAccept, p->mpConnectCallbackArg); - } - - p->mState = EState_None; - return; - } - - if (p->mpConnectCallback != nullptr) { - p->mpConnectCallback(EResult_Success, p->mpConnectCallbackArg); - } - - p->mState = EState_Receiving; - SocketCallbackFunc(SO_SUCCESS, p); -} - -/** - * @brief Socket callback function - * - * @param result Socket library result - * @param pArg User callback argument - */ -void WebSocket::SocketCallbackFunc(SOResult result, void* pArg) { - K_ASSERT_PTR(pArg); - - // User argument is this object - WebSocket* p = static_cast(pArg); - - K_LOG("SocketCallbackFunc...\n"); - K_LOG_EX("result:%d, mState:%d\n", result, p->mState); - K_UNREACHABLE(); - - // Dispatch state machine - switch (p->mState) { - case EState_Connecting: { - // Connection to the server failed - if (result != SO_SUCCESS && result != SO_EISCONN) { - if (p->mpConnectCallback != nullptr) { - p->mpConnectCallback(EResult_CantConnect, - p->mpConnectCallbackArg); - } - - p->mState = EState_None; - return; - } - break; - } - - case EState_Receiving: { - // TODO: Receive frame and then dispatch to proper state - break; - } - } -} -} // namespace kiwi diff --git a/lib/libkiwi/net/kiwiWebSocket.h b/lib/libkiwi/net/kiwiWebSocket.h deleted file mode 100644 index d81e48d..0000000 --- a/lib/libkiwi/net/kiwiWebSocket.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef LIBKIWI_NET_WEB_SOCKET_H -#define LIBKIWI_NET_WEB_SOCKET_H -#include -#include - -namespace kiwi { -//! @addtogroup libkiwi_net -//! @{ - -// Forward declarations -class HttpRequest; - -/** - * @brief WebSocket message - */ -struct WebSockMessage {}; - -/** - * @brief Asynchronous web socket - */ -class WebSocket { -public: - /** - * @brief WebSocket result codes - */ - enum EResult { - EResult_Success, //!< OK - EResult_CantConnect, //!< Can't connect to the server - EResult_CantUpgrade, //!< Can't upgrade the HTTP connection - EResult_CantAccept, //!< Can't authenticate server Accept field - }; - - /** - * @brief Generic socket operation callback - * - * @param result Socket result - * @param pArg User callback argument - */ - typedef void (*Callback)(EResult result, void* pArg); - - /** - * @brief Message receive callback - * @note If you need the message data after the callback function, make a - * copy of it before the function returns. - * - * @param pMessage Message data - * @param pArg User callback argument - */ - typedef void (*MessageCallback)(const WebSockMessage* pMessage, void* pArg); - -public: - /** - * @brief Constructor - */ - WebSocket(); - /** - * @brief Destructor - */ - ~WebSocket(); - - /** - * @brief Sets the message receive callback function - * - * @param pCallback Callback function - * @param pArg Callback user argument - */ - void SetMessageCallback(MessageCallback pCallback, void* pArg = nullptr) { - mpMessageCallback = pCallback; - mpMessageCallbackArg = pArg; - } - - /** - * @brief Connects to the specified server hostname - * - * @param rHost Server hostname - * @param pCallback Connection callback - * @param pArg Callback user argument - */ - void Connect(const String& rHost, Callback pCallback, void* pArg = nullptr); - /** - * @brief Connects to the specified server address - * - * @param rAddr Server address - * @param pCallback Connection callback - * @param pArg Callback user argument - */ - void Connect(const SockAddrAny& rAddr, Callback pCallback, - void* pArg = nullptr); - -private: - /** - * @brief Asynchronous state - */ - enum EState { - EState_None, - EState_Connecting, - EState_Receiving, - }; - -private: - /** - * @brief Socket callback function - * - * @param result Socket library result - * @param pArg User callback argument - */ - static void SocketCallbackFunc(SOResult result, void* pArg); - - /** - * @brief Request response callback function - * - * @param rResp Request response - * @param pArg Callback user argument - */ - static void RequestCallback(const HttpResponse& rResp, void* pArg); - -private: - EState mState; //!< Asynchronous state - HttpRequest* mpRequest; //!< HTTP request - - Callback mpConnectCallback; //!< Connect callback - void* mpConnectCallbackArg; //!< Connect callback user argument - - MessageCallback mpMessageCallback; //!< Message receive callback - void* mpMessageCallbackArg; //!< Message callback user argument -}; - -//! @} -} // namespace kiwi - -#endif diff --git a/lib/libkiwi/net/packet/kiwiFixedPacket.cpp b/lib/libkiwi/net/packet/kiwiFixedPacket.cpp new file mode 100644 index 0000000..db0b499 --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiFixedPacket.cpp @@ -0,0 +1,150 @@ +#include + +#include + +namespace kiwi { + +/** + * @brief Constructor + * + * @param pPeerAddr Peer socket address + */ +FixedPacket::FixedPacket(const SockAddrAny* pPeerAddr) + : PacketBase(pPeerAddr), + mpSocket(nullptr), + mStateMachine(this, EState_Max, EState_Idle) { + + mStateMachine.RegistState(EState_Idle, &FixedPacket::State_Idle_calc); + mStateMachine.RegistState(EState_Recv, &FixedPacket::State_Recv_calc); + mStateMachine.RegistState(EState_Send, &FixedPacket::State_Send_calc); +} + +/** + * @brief Sets the packet content + * + * @param pContent Packet content + * @param size Content size + */ +void FixedPacket::SetContent(const void* pContent, u32 size) { + K_ASSERT_PTR(pContent); + K_ASSERT(size > 0); + + // May need to reallocate the buffer + if (size > mBuffer.Capacity()) { + Alloc(size); + } + + u32 bytesWritten = mBuffer.Write(pContent, size); + K_ASSERT(bytesWritten == size); +} + +/** + * @brief Receives the packet over the specified socket + * + * @param pSocket Network socket + */ +void FixedPacket::Recv(SocketBase* pSocket) { + K_ASSERT_PTR(pSocket); + + mpSocket = pSocket; + mStateMachine.ChangeState(EState_Recv); +} + +/** + * @brief Sends the packet over the specified socket + * + * @param pSocket Network socket + */ +void FixedPacket::Send(SocketBase* pSocket) { + K_ASSERT_PTR(pSocket); + + mpSocket = pSocket; + mStateMachine.ChangeState(EState_Send); +} + +/** + * @brief Updates the packet state + * + * @return Whether the previous operation has just completed + */ +bool FixedPacket::Calc() { + mStateMachine.Calculate(); + return mStateMachine.IsState(EState_Idle); +} + +/** + * @brief Updates the packet in the Idle state + */ +void FixedPacket::State_Idle_calc() { + // Unlink socket when operations finish + mpSocket = nullptr; +} + +/** + * @brief Updates the packet in the Recv state + */ +void FixedPacket::State_Recv_calc() { + K_ASSERT_PTR(mpSocket); + + AutoMutexLock lock(mBufferMutex); + K_ASSERT_EX(mBuffer.IsValid(), "Fixed packet must be manually allocated"); + + if (mPeerAddr.IsValid()) { + mBuffer.Recv(mpSocket, &mPeerAddr, BufferCallback, this); + } else { + mBuffer.Recv(mpSocket, nullptr, BufferCallback, this); + } +} + +/** + * @brief Updates the packet in the Send state + */ +void FixedPacket::State_Send_calc() { + K_ASSERT_PTR(mpSocket); + + AutoMutexLock lock(mBufferMutex); + K_ASSERT_EX(mBuffer.IsValid(), "Fixed packet must be manually allocated"); + + if (mPeerAddr.IsValid()) { + mBuffer.Send(mpSocket, &mPeerAddr, BufferCallback, this); + } else { + mBuffer.Send(mpSocket, nullptr, BufferCallback, this); + } +} + +/** + * @brief Buffer transfer callback + * + * @param result Socket library result + * @param size Transfer size + * @param pArg Callback user argument + */ +void FixedPacket::BufferCallback(SOResult result, u32 size, void* pArg) { + K_ASSERT_PTR(pArg); + FixedPacket* p = static_cast(pArg); + + switch (p->mStateMachine.GetState()) { + case EState_Recv: { + // Receive is complete when the buffer is full + if (p->mBuffer.Size() == p->mBuffer.Capacity()) { + p->mStateMachine.ChangeState(EState_Idle); + } + break; + } + + case EState_Send: { + // Send is complete when the buffer has been exhausted + if (p->mBuffer.Size() == 0) { + p->mStateMachine.ChangeState(EState_Idle); + } + break; + } + + default: { + K_UNREACHABLE(); + break; + } + } +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/net/packet/kiwiFixedPacket.h b/lib/libkiwi/net/packet/kiwiFixedPacket.h new file mode 100644 index 0000000..f0950d8 --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiFixedPacket.h @@ -0,0 +1,108 @@ +#ifndef LIBKIWI_NET_FIXED_PACKET_H +#define LIBKIWI_NET_FIXED_PACKET_H +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +/** + * @brief Network packet of a fixed size + */ +class FixedPacket : public PacketBase { +public: + /** + * @brief Constructor + * + * @param pPeerAddr Peer socket address + */ + explicit FixedPacket(const SockAddrAny* pPeerAddr = nullptr); + + /** + * @brief Gets the size of the overhead needed for the packet header + */ + virtual u32 GetOverhead() const { + return 0; + } + + /** + * @brief Sets the packet content + * + * @param pContent Packet content + * @param size Content size + */ + virtual void SetContent(const void* pContent, u32 size); + + /** + * @brief Receives the packet over the specified socket + * + * @param pSocket Network socket + */ + virtual void Recv(SocketBase* pSocket); + + /** + * @brief Sends the packet over the specified socket + * + * @param pSocket Network socket + */ + virtual void Send(SocketBase* pSocket); + + /** + * @brief Updates the packet state + * + * @return Whether the previous operation has just completed + */ + virtual bool Calc(); + + /** + * @brief Updates the packet in the Idle state + */ + K_STATE_DECL(Idle); + + /** + * @brief Updates the packet in the Recv state + */ + K_STATE_DECL(Recv); + + /** + * @brief Updates the packet in the Send state + */ + K_STATE_DECL(Send); + +private: + /** + * @brief State machine state + */ + enum EState { + EState_Idle, //!< Waiting for request + EState_Recv, //!< Trying to receive packet + EState_Send, //!< Trying to send packet + + EState_Max + }; + +private: + /** + * @brief Buffer transfer callback + * + * @param result Socket library result + * @param size Transfer size + * @param pArg Callback user argument + */ + static void BufferCallback(SOResult result, u32 size, void* pArg); + +private: + //! Network socket + SocketBase* mpSocket; + //! Logic state machine + StateMachine mStateMachine; +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/packet/kiwiFixedPacketFactory.h b/lib/libkiwi/net/packet/kiwiFixedPacketFactory.h new file mode 100644 index 0000000..019a33f --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiFixedPacketFactory.h @@ -0,0 +1,38 @@ +#ifndef LIBKIWI_NET_FIXED_PACKET_FACTORY_H +#define LIBKIWI_NET_FIXED_PACKET_FACTORY_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class FixedPacket; +class SockAddrAny; + +/** + * @brief Fixed packet factory + * + * @tparam N Fixed packet size + */ +template class FixedPacketFactory : public IPacketFactory { + /** + * @brief Creates a new network packet + * + * @param pPeerAddr Peer socket address + */ + virtual FixedPacket* Create(const SockAddrAny* pPeerAddr = nullptr) { + FixedPacket* pPacket = new FixedPacket(pPeerAddr); + K_ASSERT_PTR(pPacket); + + pPacket->Alloc(N); + return pPacket; + } +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/packet/kiwiIPacketFactory.h b/lib/libkiwi/net/packet/kiwiIPacketFactory.h new file mode 100644 index 0000000..b6b24a9 --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiIPacketFactory.h @@ -0,0 +1,33 @@ +#ifndef LIBKIWI_NET_I_PACKET_FACTORY_H +#define LIBKIWI_NET_I_PACKET_FACTORY_H +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class PacketBase; + +/** + * @brief Packet factory interface + */ +class IPacketFactory { +public: + /** + * @brief Destructor + */ + virtual ~IPacketFactory() {} + + /** + * @brief Creates a new network packet + * + * @param pPeerAddr Peer socket address + */ + virtual PacketBase* Create(const SockAddrAny* pPeerAddr = nullptr) = 0; +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/packet/kiwiPacketBase.cpp b/lib/libkiwi/net/packet/kiwiPacketBase.cpp new file mode 100644 index 0000000..c339db1 --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiPacketBase.cpp @@ -0,0 +1,74 @@ +#include + +namespace kiwi { + +/** + * @brief Constructor + * + * @param pPeerAddr Peer socket address + */ +PacketBase::PacketBase(const SockAddrAny* pPeerAddr) { + K_ASSERT(pPeerAddr == nullptr || pPeerAddr->IsValid()); + + // Peer address is provided for outgoing packets + if (pPeerAddr != nullptr) { + mPeerAddr = *pPeerAddr; + } else { + mPeerAddr = SockAddr4(); + } +} + +/** + * @brief Allocates a packet buffer of the specified size + * + * @param size Packet size + */ +void PacketBase::Alloc(u32 size) { + K_ASSERT(size > 0); + K_ASSERT_EX(size < GetMaxContent(), "Must be fragmented!"); + + AutoMutexLock lock(mBufferMutex); + + // Packet type may have memory overhead from the header + mBuffer.Alloc(size + GetOverhead()); +} + +/** + * @brief Reads data from the packet + * + * @param pDst Data destination + * @param size Data size + * + * @return Number of bytes read + */ +u32 PacketBase::Read(void* pDst, u32 size) { + K_ASSERT_PTR(pDst); + + AutoMutexLock lock(mBufferMutex); + return mBuffer.Read(pDst, size); +} + +/** + * @brief Writes data to the packet + * + * @param pSrc Data source + * @param size Data size + * + * @return Number of bytes written + */ +u32 PacketBase::Write(const void* pSrc, u32 size) { + K_ASSERT_PTR(pSrc); + + AutoMutexLock lock(mBufferMutex); + return mBuffer.Write(pSrc, size); +} + +/** + * @brief Releases the packet buffer + */ +void PacketBase::Free() { + AutoMutexLock lock(mBufferMutex); + mBuffer.Free(); +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/net/packet/kiwiPacketBase.h b/lib/libkiwi/net/packet/kiwiPacketBase.h new file mode 100644 index 0000000..7950d8a --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiPacketBase.h @@ -0,0 +1,152 @@ +#ifndef LIBKIWI_NET_PACKET_BASE_H +#define LIBKIWI_NET_PACKET_BASE_H +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class SockAddrAny; + +/** + * @brief Base class for network packet implementations + */ +class PacketBase { +public: + /** + * @brief Constructor + * + * @param pPeerAddr Peer socket address + */ + explicit PacketBase(const SockAddrAny* pPeerAddr = nullptr); + + /** + * @brief Destructor + */ + virtual ~PacketBase() { + Free(); + } + + /** + * @brief Allocates a packet buffer of the specified size + * + * @param size Packet size + */ + void Alloc(u32 size); + + /** + * @brief Gets the size of the overhead needed for the packet header + */ + virtual u32 GetOverhead() const = 0; + + /** + * @brief Gets the current capacity of the packet buffer + */ + virtual u32 GetSize() const { + return mBuffer.Capacity(); + } + /** + * @brief Gets the maximum capacity of the packet buffer + */ + virtual u32 GetMaxSize() const { + return ULONG_MAX; + } + + /** + * @brief Gets the current capacity of the packet content + */ + virtual u32 GetContentSize() const { + return GetSize() - GetOverhead(); + } + /** + * @brief Gets the maximum capacity of the packet content + */ + virtual u32 GetMaxContent() const { + return GetMaxSize() - GetOverhead(); + } + + /** + * @brief Accesses the packet content + */ + virtual const void* GetContent() const { + return mBuffer.Data() + GetOverhead(); + } + + /** + * @brief Sets the packet content + * + * @param pContent Packet content + * @param size Content size + */ + virtual void SetContent(const void* pContent, u32 size) = 0; + + /** + * @brief Receives the packet over the specified socket + * + * @param pSocket Network socket + */ + virtual void Recv(SocketBase* pSocket) = 0; + + /** + * @brief Sends the packet over the specified socket + * + * @param pSocket Network socket + */ + virtual void Send(SocketBase* pSocket) = 0; + + /** + * @brief Updates the packet state + * + * @return Whether the previous operation has just completed + */ + virtual bool Calc() = 0; + + /** + * @brief Reads data from the packet + * + * @param pDst Data destination + * @param size Data size + * + * @return Number of bytes read + */ + u32 Read(void* pDst, u32 size); + + /** + * @brief Writes data to the packet + * + * @param pSrc Data source + * @param size Data size + * + * @return Number of bytes written + */ + u32 Write(const void* pSrc, u32 size); + + /** + * @brief Accesses the peer socket address + */ + const SockAddrAny& GetPeerAddr() const { + return mPeerAddr; + } + +protected: + /** + * @brief Releases the packet buffer + */ + void Free(); + +protected: + //! Packet data buffer + detail::NetBuffer mBuffer; + //! Buffer access mutex + Mutex mBufferMutex; + + //! Peer socket address + SockAddrAny mPeerAddr; +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/packet/kiwiPacketFactory.h b/lib/libkiwi/net/packet/kiwiPacketFactory.h new file mode 100644 index 0000000..880e45e --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiPacketFactory.h @@ -0,0 +1,34 @@ +#ifndef LIBKIWI_NET_PACKET_FACTORY_H +#define LIBKIWI_NET_PACKET_FACTORY_H +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class SockAddrAny; + +/** + * @brief Generic packet factory + * + * @tparam T Packet class type + */ +template class TPacketFactory : public IPacketFactory { + /** + * @brief Creates a new network packet + * + * @param pPeerAddr Peer socket address + */ + virtual T* Create(const SockAddrAny* pPeerAddr = nullptr) { + T* pPacket = new T(pPeerAddr); + K_ASSERT_PTR(pPacket); + return pPacket; + } +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/packet/kiwiVariablePacket.cpp b/lib/libkiwi/net/packet/kiwiVariablePacket.cpp new file mode 100644 index 0000000..366d130 --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiVariablePacket.cpp @@ -0,0 +1,152 @@ +#include + +#include + +namespace kiwi { + +/** + * @brief Constructor + * + * @param pPeerAddr Peer socket address + */ +VariablePacket::VariablePacket(const SockAddrAny* pPeerAddr) + : PacketBase(pPeerAddr), + mpSocket(nullptr), + mStateMachine(this, EState_Max, EState_Idle) { + + mStateMachine.RegistState(EState_Idle, &VariablePacket::State_Idle_calc); + mStateMachine.RegistState(EState_Recv, &VariablePacket::State_Recv_calc); + mStateMachine.RegistState(EState_Send, &VariablePacket::State_Send_calc); +} + +/** + * @brief Sets the packet content + * + * @param pContent Packet content + * @param size Content size + */ +void VariablePacket::SetContent(const void* pContent, u32 size) { + K_ASSERT_PTR(pContent); + K_ASSERT(size > 0); + + // May need to reallocate the buffer + if (size > mBuffer.Capacity()) { + Alloc(size); + } + + u32 bytesWritten = mBuffer.Write(pContent, size); + K_ASSERT(bytesWritten == size); +} + +/** + * @brief Receives the packet over the specified socket + * + * @param pSocket Network socket + */ +void VariablePacket::Recv(SocketBase* pSocket) { + K_ASSERT_PTR(pSocket); + + mpSocket = pSocket; + mStateMachine.ChangeState(EState_Recv); +} + +/** + * @brief Sends the packet over the specified socket + * + * @param pSocket Network socket + */ +void VariablePacket::Send(SocketBase* pSocket) { + K_ASSERT_PTR(pSocket); + + mpSocket = pSocket; + mStateMachine.ChangeState(EState_Send); +} + +/** + * @brief Updates the packet state + * + * @return Whether the previous operation has just completed + */ +bool VariablePacket::Calc() { + mStateMachine.Calculate(); + return mStateMachine.IsState(EState_Idle); +} + +/** + * @brief Updates the packet in the Idle state + */ +void VariablePacket::State_Idle_calc() { + // Unlink socket when operations finish + mpSocket = nullptr; +} + +/** + * @brief Updates the packet in the Recv state + */ +void VariablePacket::State_Recv_calc() { + K_ASSERT_PTR(mpSocket); + + AutoMutexLock lock(mBufferMutex); + K_ASSERT_EX(mBuffer.IsValid(), + "Variable packet must be manually allocated"); + + if (mPeerAddr.IsValid()) { + mBuffer.Recv(mpSocket, &mPeerAddr, BufferCallback, this); + } else { + mBuffer.Recv(mpSocket, nullptr, BufferCallback, this); + } +} + +/** + * @brief Updates the packet in the Send state + */ +void VariablePacket::State_Send_calc() { + K_ASSERT_PTR(mpSocket); + + AutoMutexLock lock(mBufferMutex); + K_ASSERT_EX(mBuffer.IsValid(), + "Variable packet must be manually allocated"); + + if (mPeerAddr.IsValid()) { + mBuffer.Send(mpSocket, &mPeerAddr, BufferCallback, this); + } else { + mBuffer.Send(mpSocket, nullptr, BufferCallback, this); + } +} + +/** + * @brief Buffer transfer callback + * + * @param result Socket library result + * @param size Transfer size + * @param pArg Callback user argument + */ +void VariablePacket::BufferCallback(SOResult result, u32 size, void* pArg) { + K_ASSERT_PTR(pArg); + VariablePacket* p = static_cast(pArg); + + switch (p->mStateMachine.GetState()) { + case EState_Recv: { + // Receive is complete once any data is received + if (p->mBuffer.Size() > 0) { + p->mStateMachine.ChangeState(EState_Idle); + } + break; + } + + case EState_Send: { + // Send is complete when the buffer has been exhausted + if (p->mBuffer.Size() == 0) { + p->mStateMachine.ChangeState(EState_Idle); + } + break; + } + + default: { + K_UNREACHABLE(); + break; + } + } +} + +} // namespace kiwi \ No newline at end of file diff --git a/lib/libkiwi/net/packet/kiwiVariablePacket.h b/lib/libkiwi/net/packet/kiwiVariablePacket.h new file mode 100644 index 0000000..a4c3b72 --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiVariablePacket.h @@ -0,0 +1,115 @@ +#ifndef LIBKIWI_NET_VARIABLE_PACKET_H +#define LIBKIWI_NET_VARIABLE_PACKET_H +#include +#include +#include + +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +/** + * @brief Network packet of a variable size + */ +class VariablePacket : public PacketBase { +public: + /** + * @brief Constructor + * + * @param pPeerAddr Peer socket address + */ + explicit VariablePacket(const SockAddrAny* pPeerAddr = nullptr); + + /** + * @brief Gets the size of the overhead needed for the packet header + */ + virtual u32 GetOverhead() const { + return 0; + } + + /** + * @brief Gets the current capacity of the packet buffer + */ + virtual u32 GetSize() const { + return mBuffer.Size(); + } + + /** + * @brief Sets the packet content + * + * @param pContent Packet content + * @param size Content size + */ + virtual void SetContent(const void* pContent, u32 size); + + /** + * @brief Receives the packet over the specified socket + * + * @param pSocket Network socket + */ + virtual void Recv(SocketBase* pSocket); + + /** + * @brief Sends the packet over the specified socket + * + * @param pSocket Network socket + */ + virtual void Send(SocketBase* pSocket); + + /** + * @brief Updates the packet state + * + * @return Whether the previous operation has just completed + */ + virtual bool Calc(); + + /** + * @brief Updates the packet in the Idle state + */ + K_STATE_DECL(Idle); + + /** + * @brief Updates the packet in the Recv state + */ + K_STATE_DECL(Recv); + + /** + * @brief Updates the packet in the Send state + */ + K_STATE_DECL(Send); + +private: + /** + * @brief State machine state + */ + enum EState { + EState_Idle, //!< Waiting for request + EState_Recv, //!< Trying to receive packet + EState_Send, //!< Trying to send packet + + EState_Max + }; + +private: + /** + * @brief Buffer transfer callback + * + * @param result Socket library result + * @param size Transfer size + * @param pArg Callback user argument + */ + static void BufferCallback(SOResult result, u32 size, void* pArg); + +private: + //! Network socket + SocketBase* mpSocket; + //! Logic state machine + StateMachine mStateMachine; +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/net/packet/kiwiVariablePacketFactory.h b/lib/libkiwi/net/packet/kiwiVariablePacketFactory.h new file mode 100644 index 0000000..4e65221 --- /dev/null +++ b/lib/libkiwi/net/packet/kiwiVariablePacketFactory.h @@ -0,0 +1,38 @@ +#ifndef LIBKIWI_NET_VARIABLE_PACKET_FACTORY_H +#define LIBKIWI_NET_VARIABLE_PACKET_FACTORY_H +#include +#include +#include + +namespace kiwi { +//! @addtogroup libkiwi_net +//! @{ + +// Forward declarations +class VariablePacket; +class SockAddrAny; + +/** + * @brief Variable packet factory + * + * @tparam N Variable packet size + */ +template class VariablePacketFactory : public IPacketFactory { + /** + * @brief Creates a new network packet + * + * @param pPeerAddr Peer socket address + */ + virtual VariablePacket* Create(const SockAddrAny* pPeerAddr = nullptr) { + VariablePacket* pPacket = new VariablePacket(pPeerAddr); + K_ASSERT_PTR(pPacket); + + pPacket->Alloc(N); + return pPacket; + } +}; + +//! @} +} // namespace kiwi + +#endif diff --git a/lib/libkiwi/resource/kiwiResourceMgr.cpp b/lib/libkiwi/resource/kiwiResourceMgr.cpp index 93a8886..59e510f 100644 --- a/lib/libkiwi/resource/kiwiResourceMgr.cpp +++ b/lib/libkiwi/resource/kiwiResourceMgr.cpp @@ -310,7 +310,7 @@ void ResourceMgr::LoadCacheArchives() { K_ASSERT_PTR(pCommonResource); - // TODO: Why only Wii Play? Are the local archives just that small? + // TODO(kiwi) Why only Wii Play? Are the local archives just that small? #if defined(PACK_PLAY) // Not enough memory to decompress these all ahead of time const Resource* pLocalResource = diff --git a/lib/libkiwi/support/kiwiLibSO.cpp b/lib/libkiwi/support/kiwiLibSO.cpp index 12feb67..ae41aa8 100644 --- a/lib/libkiwi/support/kiwiLibSO.cpp +++ b/lib/libkiwi/support/kiwiLibSO.cpp @@ -478,6 +478,7 @@ s32 LibSO::RecvImpl(SOSocket socket, void* dst, u32 len, u32 flags, s32 result = sDevNetIpTop.IoctlV(Ioctl_SORecvFrom, input, output); sLastError = result >= 0 ? SO_SUCCESS : static_cast(result); + // Peer address if (sLastError == SO_SUCCESS) { if (addr != NULL) { *addr = *from; @@ -766,7 +767,7 @@ bool LibSO::ResolveHostName(SockAddrAny& addr, const String& name, IosString iService(service); input.PushBack(iService); - // TODO: Would other hints be useful? + // TODO(kiwi) Would other hints be useful? IosObject iHints; std::memset(iHints.Base(), 0, iHints.Length()); iHints->type = type; @@ -804,7 +805,7 @@ bool LibSO::ResolveHostName(SockAddrAny& addr, const String& name, continue; } - // TODO: Why does Dolphin provide bad length values? + // TODO(kiwi) Why does Dolphin provide bad length values? // // IP version doesn't match // if (addr.len != 0 && rInfo.len != addr.len) { // continue; @@ -818,7 +819,7 @@ bool LibSO::ResolveHostName(SockAddrAny& addr, const String& name, return false; } - // TODO: Dolphin seems to give bad length, so we fix it after the copy + // TODO(kiwi) Dolphin seems to give bad length, so we fix it after the copy u32 len = addr.len; addr = *pFoundAddr; addr.len = len; @@ -840,7 +841,7 @@ SOResult LibSO::GetSockOpt(SOSocket socket, SOSockOptLevel level, SOSockOpt opt, void* val, u32 len) { K_ASSERT_EX(sDevNetIpTop.IsOpen(), "Please call LibSO::Initialize"); - // TODO: Implement + // TODO(kiwi) Implement K_ASSERT_EX(false, "Not implemented."); sLastError = SO_SUCCESS; diff --git a/lib/libkiwi/util/kiwiIosObject.h b/lib/libkiwi/util/kiwiIosObject.h index 426e825..5b4b83b 100644 --- a/lib/libkiwi/util/kiwiIosObject.h +++ b/lib/libkiwi/util/kiwiIosObject.h @@ -91,7 +91,7 @@ template class IosObject : public IosBuffer { /** * @brief Access data length */ - // TODO: Hack to make this function specializable by template... + // TODO(kiwi) Hack to make this function specializable by template... virtual u32 Length() const { return IosVector::Length(); } diff --git a/lib/libkiwi/util/kiwiStateMachine.h b/lib/libkiwi/util/kiwiStateMachine.h index 3431470..5457554 100644 --- a/lib/libkiwi/util/kiwiStateMachine.h +++ b/lib/libkiwi/util/kiwiStateMachine.h @@ -104,6 +104,13 @@ template class StateMachine { mExiting = true; } + /** + * @brief Gets the current state ID + */ + s32 GetState() const { + return mState; + } + /** * @brief Tests whether the machine is in the specified state * diff --git a/src/core/CheckMgr.cpp b/src/Cmn/CheckMgr.cpp similarity index 94% rename from src/core/CheckMgr.cpp rename to src/Cmn/CheckMgr.cpp index 19b95ef..5c5eebc 100644 --- a/src/core/CheckMgr.cpp +++ b/src/Cmn/CheckMgr.cpp @@ -1,13 +1,14 @@ -#include "core/CheckMgr.h" +#include "Cmn/CheckMgr.h" -#include "core/ItemMgr.h" -#include "core/checks.h" +#include "Cmn/ItemMgr.h" +#include "checks.h" #include -K_DYNAMIC_SINGLETON_IMPL(AP::CheckMgr); +K_DYNAMIC_SINGLETON_IMPL(AP::Cmn::CheckMgr); namespace AP { +namespace Cmn { /** * @brief Gets the readable name of the specified check ID @@ -113,4 +114,5 @@ void CheckMgr::GiveCheckItem(CheckID id) const { ItemMgr::GetInstance().SetItemState(item, true); } +} // namespace Cmn } // namespace AP diff --git a/src/core/CheckMgr.h b/src/Cmn/CheckMgr.h similarity index 93% rename from src/core/CheckMgr.h rename to src/Cmn/CheckMgr.h index 1547d61..ef82fea 100644 --- a/src/core/CheckMgr.h +++ b/src/Cmn/CheckMgr.h @@ -1,13 +1,13 @@ -#ifndef APCLIENT_CORE_CHECK_MGR_H -#define APCLIENT_CORE_CHECK_MGR_H +#ifndef APCLIENT_CMN_CHECK_MGR_H +#define APCLIENT_CMN_CHECK_MGR_H #include -#include "core/const.h" -#include +#include "const.h" #include namespace AP { +namespace Cmn { /** * @brief Archipelago check manager @@ -98,6 +98,7 @@ class CheckMgr : public kiwi::DynamicSingleton { kiwi::THashMap mCheckToItemID; }; +} // namespace Cmn } // namespace AP -#endif // APCLIENT_CORE_CHECK_MGR_H +#endif diff --git a/src/core/CosmeticMgr.cpp b/src/Cmn/CosmeticMgr.cpp similarity index 93% rename from src/core/CosmeticMgr.cpp rename to src/Cmn/CosmeticMgr.cpp index 106cef9..72b444d 100644 --- a/src/core/CosmeticMgr.cpp +++ b/src/Cmn/CosmeticMgr.cpp @@ -1,10 +1,11 @@ -#include "core/CosmeticMgr.h" +#include "Cmn/CosmeticMgr.h" #include -K_DYNAMIC_SINGLETON_IMPL(AP::CosmeticMgr); +K_DYNAMIC_SINGLETON_IMPL(AP::Cmn::CosmeticMgr); namespace AP { +namespace Cmn { /** * @brief Constructor @@ -63,4 +64,5 @@ void CosmeticMgr::Debug() { } } +} // namespace Cmn } // namespace AP diff --git a/src/core/CosmeticMgr.h b/src/Cmn/CosmeticMgr.h similarity index 95% rename from src/core/CosmeticMgr.h rename to src/Cmn/CosmeticMgr.h index 1005cbf..b5cdb3e 100644 --- a/src/core/CosmeticMgr.h +++ b/src/Cmn/CosmeticMgr.h @@ -1,14 +1,15 @@ -#ifndef APCLIENT_CORE_COSMETIC_MGR_H -#define APCLIENT_CORE_COSMETIC_MGR_H +#ifndef APCLIENT_CMN_COSMETIC_MGR_H +#define APCLIENT_CMN_COSMETIC_MGR_H #include -#include "core/const.h" +#include "const.h" #include #include #include namespace AP { +namespace Cmn { /** * @brief Archipelago cosmetic manager @@ -105,6 +106,7 @@ class CosmeticMgr : public kiwi::DynamicSingleton { RPSysScene::ETime mRandomTimeMapping[Sp2::Cmn::EGroupID_Max + 1]; }; +} // namespace Cmn } // namespace AP #endif diff --git a/src/core/ItemMgr.cpp b/src/Cmn/ItemMgr.cpp similarity index 99% rename from src/core/ItemMgr.cpp rename to src/Cmn/ItemMgr.cpp index edc3af8..9d7bf85 100644 --- a/src/core/ItemMgr.cpp +++ b/src/Cmn/ItemMgr.cpp @@ -1,12 +1,13 @@ -#include "core/ItemMgr.h" +#include "Cmn/ItemMgr.h" -#include "core/items.h" +#include "items.h" #include -K_DYNAMIC_SINGLETON_IMPL(AP::ItemMgr); +K_DYNAMIC_SINGLETON_IMPL(AP::Cmn::ItemMgr); namespace AP { +namespace Cmn { /** * @brief Gets the readable name of the specified item ID @@ -329,7 +330,7 @@ bool ItemMgr::GetItemState(ItemID id) const { } // Frisbee Dog - case ITEM_FRISBEE_DOG_FRISBEES: { + case ITEM_FRISBEE_DOG_PROG_FRISBEES: { return mFldThrowFlag.Count(); } case ITEM_FRISBEE_DOG_SECRET_POP: { @@ -665,7 +666,7 @@ void ItemMgr::SetItemState(ItemID id, bool state) { } // Frisbee Dog - case ITEM_FRISBEE_DOG_FRISBEES: { + case ITEM_FRISBEE_DOG_PROG_FRISBEES: { mFldThrowFlag.SetFirstUnset(); break; } @@ -945,4 +946,5 @@ void ItemMgr::SetItemState(ItemID id, bool state) { } } +} // namespace Cmn } // namespace AP diff --git a/src/core/ItemMgr.h b/src/Cmn/ItemMgr.h similarity index 99% rename from src/core/ItemMgr.h rename to src/Cmn/ItemMgr.h index 5c7ebe8..4550cd0 100644 --- a/src/core/ItemMgr.h +++ b/src/Cmn/ItemMgr.h @@ -1,13 +1,14 @@ -#ifndef APCLIENT_CORE_ITEM_MGR_H -#define APCLIENT_CORE_ITEM_MGR_H +#ifndef APCLIENT_CMN_ITEM_MGR_H +#define APCLIENT_CMN_ITEM_MGR_H #include -#include "core/const.h" +#include "const.h" #include #include namespace AP { +namespace Cmn { /** * @brief Archipelago item manager @@ -686,6 +687,7 @@ class ItemMgr : public kiwi::DynamicSingleton { /**@}*/ }; +} // namespace Cmn } // namespace AP #endif diff --git a/src/Cmn/System.cpp b/src/Cmn/System.cpp new file mode 100644 index 0000000..264241e --- /dev/null +++ b/src/Cmn/System.cpp @@ -0,0 +1,30 @@ +#include "Cmn/System.h" + +#include "Cmn/CheckMgr.h" +#include "Cmn/CosmeticMgr.h" +#include "Cmn/ItemMgr.h" +#include "Net/NetworkMgr.h" + +namespace AP { +namespace Cmn { + +/** + * @brief Performs initialization for required objects + */ +void System::Initialize() { + ItemMgr::CreateInstance(); + CosmeticMgr::CreateInstance(); + CheckMgr::CreateInstance(); + + // TODO: Move to debug menu eventually +#ifndef NDEBUG + ItemMgr::GetInstance().Debug(); + CosmeticMgr::GetInstance().Debug(); + CheckMgr::GetInstance().Debug(); +#endif + + Net::NetworkMgr::CreateInstance(); +} + +} // namespace Cmn +} // namespace AP diff --git a/src/Cmn/System.h b/src/Cmn/System.h new file mode 100644 index 0000000..76f9d3a --- /dev/null +++ b/src/Cmn/System.h @@ -0,0 +1,22 @@ +#ifndef APCLIENT_CMN_SYSTEM_H +#define APCLIENT_CMN_SYSTEM_H +#include + +namespace AP { +namespace Cmn { + +/** + * @brief App initialization + */ +class System { +public: + /** + * @brief Performs initialization for required objects + */ + static void Initialize(); +}; + +} // namespace Cmn +} // namespace AP + +#endif \ No newline at end of file diff --git a/src/Net/IMessage.h b/src/Net/IMessage.h new file mode 100644 index 0000000..1b5b7af --- /dev/null +++ b/src/Net/IMessage.h @@ -0,0 +1,37 @@ +#ifndef APCLIENT_NET_I_MESSAGE_H +#define APCLIENT_NET_I_MESSAGE_H +#include + +namespace AP { +namespace Net { + +/** + * @brief Network message interface + */ +class IMessage { +public: + /** + * @brief Command type + */ + enum EKind { + EKind_Connect, + EKind_Disconnect, + EKind_Item, + }; + +public: + /** + * @brief Destructor + */ + virtual ~IMessage() {} + + /** + * @brief Gets the type of this message + */ + virtual EKind GetKind() const = 0; +}; + +} // namespace Net +} // namespace AP + +#endif diff --git a/src/Net/IMessageListener.h b/src/Net/IMessageListener.h new file mode 100644 index 0000000..78df47c --- /dev/null +++ b/src/Net/IMessageListener.h @@ -0,0 +1,32 @@ +#ifndef APCLIENT_NET_I_MESSAGE_LISTENER_H +#define APCLIENT_NET_I_MESSAGE_LISTENER_H +#include + +namespace AP { +namespace Net { + +// Forward declarations +class IMessage; + +/** + * @brief Network message listener interface + */ +class IMessageListener { +public: + /** + * @brief Destructor + */ + virtual ~IMessageListener() {} + + /** + * @brief Handles a new network message + * + * @param pMessage Network message + */ + virtual void OnMessage(IMessage* pMessage) = 0; +}; + +} // namespace Net +} // namespace AP + +#endif diff --git a/src/Net/NetworkMgr.cpp b/src/Net/NetworkMgr.cpp new file mode 100644 index 0000000..f272179 --- /dev/null +++ b/src/Net/NetworkMgr.cpp @@ -0,0 +1,125 @@ +#include "Net/NetworkMgr.h" + +#include "Net/IMessage.h" +#include "Net/IMessageListener.h" +#include "Net/msg/ConnectMsg.h" +#include "Net/msg/DisconnectMsg.h" +#include "Net/msg/ItemMsg.h" +#include "packets.h" + +#include + +K_DYNAMIC_SINGLETON_IMPL(AP::Net::NetworkMgr); + +namespace AP { +namespace Net { + +/** + * @brief Constructor + */ +NetworkMgr::NetworkMgr() { + bool success = false; + + // Create server socket + mpSocket = new kiwi::SyncSocket(SO_PF_INET, SO_SOCK_DGRAM); + ASSERT_PTR(mpSocket); + + // TODO(kiwi) Can we remove this? + mpSocket->SetBlocking(false); + + // Create server connection + mpServer = new kiwi::NetServer( + mpSocket, new kiwi::VariablePacketFactory()); + + ASSERT_PTR(mpServer); + + // Bind to any available local address + kiwi::SockAddr4 addr(kiwi::port::AP_COMM); + success = mpServer->Bind(addr); + ASSERT_EX(success, "Can't bind socket"); + + // Register callback to handle PC client packets + mpServer->SetRecvCallback(PacketCallback, this); + + // Show IP address in the console + u16 port = addr.port; + mpSocket->GetHostAddr(addr); + addr.port = port; + + LOG_EX("NetworkMgr listening on: %s\n", kiwi::ToString(addr).CStr()); +} + +/** + * @brief Destructor + */ +NetworkMgr::~NetworkMgr() { + delete mpServer; + mpServer = nullptr; + + delete mpSocket; + mpSocket = nullptr; +} + +/** + * @brief Packet receive callback + * + * @param pPacket Incoming packet + * @param pArg Callback user argument + */ +void NetworkMgr::PacketCallback(kiwi::PacketBase* pPacket, void* pArg) { + ASSERT_PTR(pPacket); + ASSERT_PTR(pArg); + + IMessage* pMessage = nullptr; + + // Callback argument is this object + NetworkMgr* p = static_cast(pArg); + + const void* pContent = pPacket->GetContent(); + u32 contentSize = pPacket->GetContentSize(); + kiwi::MemStream contentStrm(pContent, contentSize); + + // Every packet's data begins with the common fields + u8 kind = contentStrm.Read_u8(); + + // TODO(kiwi) Struct size is wrong even when byte-packed + // #define HANDLE_PACKET(NAME) + // case IMessage::EKind_##NAME: { + // if (contentSize != sizeof(NAME##Packet)) { + // LOG_EX("Illegal " #NAME " Packet (want %d bytes, got %d)\n", + // sizeof(ConnectPacket), contentSize); + // } + // + // pMessage = new NAME##Msg(contentStrm); + // break; + // } + +#define HANDLE_PACKET(NAME) \ + case IMessage::EKind_##NAME: { \ + pMessage = new NAME##Msg(contentStrm); \ + break; \ + } + + switch (kind) { + HANDLE_PACKET(Connect); + HANDLE_PACKET(Disconnect); + HANDLE_PACKET(Item); + + default: { + ASSERT_EX(false, "Unknown packet type: %d", kind); + break; + } + } + +#undef HANDLE_PACKET + + // Notify listeners + if (pMessage != nullptr) { + K_FOREACH (it, p->mListenerList) { + (*it)->OnMessage(pMessage); + } + } +} + +} // namespace Net +} // namespace AP \ No newline at end of file diff --git a/src/Net/NetworkMgr.h b/src/Net/NetworkMgr.h new file mode 100644 index 0000000..f872e8e --- /dev/null +++ b/src/Net/NetworkMgr.h @@ -0,0 +1,66 @@ +#ifndef APCLIENT_NET_NETWORK_MGR_H +#define APCLIENT_NET_NETWORK_MGR_H +#include + +#include + +namespace AP { +namespace Net { + +// Forward declarations +class IMessageListener; + +/** + * @brief Archipelago connection + */ +class NetworkMgr : public kiwi::DynamicSingleton { + friend class kiwi::DynamicSingleton; + +public: + /** + * @brief Registers a new message listener + * + * @param pListener Message listener + */ + void RegistListener(IMessageListener* pListener) { + ASSERT_PTR(pListener); + mListenerList.PushBack(pListener); + } + +private: + //! Maximum datagram packet size from the PC client + static const u32 MAX_PACKET_SIZE = 512; + +private: + /** + * @brief Constructor + */ + NetworkMgr(); + + /** + * @brief Destructor + */ + ~NetworkMgr(); + + /** + * @brief Packet receive callback + * + * @param pPacket Incoming packet + * @param pArg Callback user argument + */ + static void PacketCallback(kiwi::PacketBase* pPacket, void* pArg); + +private: + //! Server socket + kiwi::SyncSocket* mpSocket; + //! Server connection + kiwi::NetServer* mpServer; + + //! Registered message listeners + kiwi::TList mListenerList; +}; + +} // namespace Net +} // namespace AP + +#endif diff --git a/src/Net/msg/ConnectMsg.cpp b/src/Net/msg/ConnectMsg.cpp new file mode 100644 index 0000000..cd1ad6c --- /dev/null +++ b/src/Net/msg/ConnectMsg.cpp @@ -0,0 +1,24 @@ +#include "Net/msg/ConnectMsg.h" + +#include + +namespace AP { +namespace Net { + +/** + * @brief Constructor + * + * @param rStrm Stream to packet content + */ +ConnectMsg::ConnectMsg(kiwi::MemStream& rStrm) { + u32 addr = rStrm.Read_u32(); + u16 port = rStrm.Read_u16(); + + mPeerAddr = kiwi::SockAddr4(addr, port); + + K_LOG_EX("Received ConnectMsg from: %s\n", + kiwi::ToString(mPeerAddr).CStr()); +} + +} // namespace Net +} // namespace AP \ No newline at end of file diff --git a/src/Net/msg/ConnectMsg.h b/src/Net/msg/ConnectMsg.h new file mode 100644 index 0000000..7945c2f --- /dev/null +++ b/src/Net/msg/ConnectMsg.h @@ -0,0 +1,47 @@ +#ifndef APCLIENT_NET_MSG_CONNECT_MSG_H +#define APCLIENT_NET_MSG_CONNECT_MSG_H +#include + +#include "Net/IMessage.h" +#include "packets.h" + +#include + +namespace AP { +namespace Net { + +/** + * @brief PC client connection message + */ +class ConnectMsg : public IMessage { +public: + /** + * @brief Constructor + * + * @param rStrm Stream to packet content + */ + ConnectMsg(kiwi::MemStream& rStrm); + + /** + * @brief Gets the type of this command + */ + virtual EKind GetKind() const { + return EKind_Connect; + } + + /** + * @brief Accesses the peer socket address + */ + const kiwi::SockAddr4& GetPeerAddr() const { + return mPeerAddr; + } + +private: + //! Peer socket address + kiwi::SockAddr4 mPeerAddr; +}; + +} // namespace Net +} // namespace AP + +#endif diff --git a/src/Net/msg/DisconnectMsg.h b/src/Net/msg/DisconnectMsg.h new file mode 100644 index 0000000..843e1eb --- /dev/null +++ b/src/Net/msg/DisconnectMsg.h @@ -0,0 +1,33 @@ +#ifndef APCLIENT_NET_MSG_DISCONNECT_MSG_H +#define APCLIENT_NET_MSG_DISCONNECT_MSG_H +#include + +#include "Net/IMessage.h" + +namespace AP { +namespace Net { + +/** + * @brief PC client disconnection message + */ +class DisconnectMsg : public IMessage { +public: + /** + * @brief Constructor + * + * @param rStrm Stream to packet content + */ + DisconnectMsg(kiwi::MemStream& /* rStrm */) {} + + /** + * @brief Gets the type of this command + */ + virtual EKind GetKind() const { + return EKind_Disconnect; + } +}; + +} // namespace Net +} // namespace AP + +#endif diff --git a/src/Net/msg/ItemMsg.h b/src/Net/msg/ItemMsg.h new file mode 100644 index 0000000..d092ce8 --- /dev/null +++ b/src/Net/msg/ItemMsg.h @@ -0,0 +1,33 @@ +#ifndef APCLIENT_NET_MSG_ITEM_MSG_H +#define APCLIENT_NET_MSG_ITEM_MSG_H +#include + +#include "Net/IMessage.h" + +namespace AP { +namespace Net { + +/** + * @brief Item message + */ +class ItemMsg : public IMessage { +public: + /** + * @brief Constructor + * + * @param rStrm Stream to packet content + */ + ItemMsg(kiwi::MemStream& /* rStrm */) {} + + /** + * @brief Gets the type of this command + */ + virtual EKind GetKind() const { + return EKind_Item; + } +}; + +} // namespace Net +} // namespace AP + +#endif diff --git a/src/hooks/Arc/checks_Arc.cpp b/src/Scene/Arc/checks_Arc.cpp similarity index 77% rename from src/hooks/Arc/checks_Arc.cpp rename to src/Scene/Arc/checks_Arc.cpp index 716c470..43dedb4 100644 --- a/src/hooks/Arc/checks_Arc.cpp +++ b/src/Scene/Arc/checks_Arc.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Arc { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Arc { * ******************************************************************************/ - +} // namespace Check } // namespace Arc } // namespace AP \ No newline at end of file diff --git a/src/hooks/Arc/items_Arc.cpp b/src/Scene/Arc/items_Arc.cpp similarity index 83% rename from src/hooks/Arc/items_Arc.cpp rename to src/Scene/Arc/items_Arc.cpp index 841bbc4..36039bc 100644 --- a/src/hooks/Arc/items_Arc.cpp +++ b/src/Scene/Arc/items_Arc.cpp @@ -1,11 +1,12 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Arc { +namespace Item { /****************************************************************************** * @@ -17,7 +18,7 @@ namespace Arc { * @brief Sets the aim flag in Archery */ bool ArcSetAimFlag(bool hold2) { - if (!ItemMgr::GetInstance().IsArcAim()) + if (!Cmn::ItemMgr::GetInstance().IsArcAim()) return false; else if (!hold2) return false; @@ -72,12 +73,12 @@ bool ArcSetFruitFlag(int stageID) { break; default: - K_LOG_EX("stageID: %d\n", stageID); - K_LOG_EX("difficulty: %d\n", difficulty); - K_ASSERT(false); + LOG_EX("stageID: %d\n", stageID); + LOG_EX("difficulty: %d\n", difficulty); + ASSERT(false); } - return ItemMgr::GetInstance().IsArcFruitUnlock(difficulty) == 1; + return Cmn::ItemMgr::GetInstance().IsArcFruitUnlock(difficulty) == 1; } /** @@ -113,7 +114,7 @@ TRAMPOLINE_DEF(0x8057cbe0, 0x8057cbe4){ * @brief Sets the max arrow count in Archery */ u32 ArcSetMaxArrowCount() { - return ItemMgr::GetInstance().GetArcArrowNum(); + return Cmn::ItemMgr::GetInstance().GetArcArrowNum(); } /** @@ -132,5 +133,6 @@ TRAMPOLINE_DEF(0x8056aaac, 0x8056aab0) { // clang-format on } +} // namespace Item } // namespace Arc } // namespace AP diff --git a/src/hooks/Bic/checks_Bic.cpp b/src/Scene/Bic/checks_Bic.cpp similarity index 77% rename from src/hooks/Bic/checks_Bic.cpp rename to src/Scene/Bic/checks_Bic.cpp index 4301f84..3d38f1e 100644 --- a/src/hooks/Bic/checks_Bic.cpp +++ b/src/Scene/Bic/checks_Bic.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Bic { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Bic { * ******************************************************************************/ - +} // namespace Check } // namespace Bic } // namespace AP \ No newline at end of file diff --git a/src/hooks/Bic/items_Bic.cpp b/src/Scene/Bic/items_Bic.cpp similarity index 83% rename from src/hooks/Bic/items_Bic.cpp rename to src/Scene/Bic/items_Bic.cpp index 6a9ab1f..0dc8552 100644 --- a/src/hooks/Bic/items_Bic.cpp +++ b/src/Scene/Bic/items_Bic.cpp @@ -1,11 +1,12 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Bic { +namespace Item { /****************************************************************************** * @@ -17,7 +18,7 @@ namespace Bic { * @brief Maximum energy per heart amount * @details hearts = ceil((E - 0.1f) * 3 / 0.7f) */ -static const f32 scHeartMaxEnergy[ItemMgr::BIC_HEART_COUNT + 1] = { +static const f32 HEART_MAX_ENERGY[Cmn::ItemMgr::BIC_HEART_COUNT + 1] = { 0.100000f, // Zero hearts 0.333333f, // One heart 0.566666f, // Two hearts @@ -32,7 +33,7 @@ static const f32 scHeartMaxEnergy[ItemMgr::BIC_HEART_COUNT + 1] = { void BicInitHeartNum(Sp2::Bic::Cyclist* pCyclist) { ASSERT(pCyclist != nullptr); - pCyclist->setHeartNum(ItemMgr::GetInstance().GetBicHeartNum()); + pCyclist->setHeartNum(Cmn::ItemMgr::GetInstance().GetBicHeartNum()); } /** @@ -60,7 +61,8 @@ f32 BicCalcEnergy(Sp2::Bic::Cyclist* pCyclist, f32 energy) { energy = kiwi::Clamp(energy, 0.0f, 1.0f); // Energy is capped by heart AP items - f32 energyLimit = scHeartMaxEnergy[ItemMgr::GetInstance().GetBicHeartNum()]; + f32 energyLimit = + HEART_MAX_ENERGY[Cmn::ItemMgr::GetInstance().GetBicHeartNum()]; energy = kiwi::Min(energy, energyLimit); pCyclist->setEnergy(energy); @@ -89,8 +91,10 @@ void BicCalcDrinking(Sp2::Bic::Cyclist* pCyclist) { ASSERT(pCyclist != nullptr); ASSERT(pCyclist->getState() == Sp2::Bic::Cyclist::EState_Drinking); + f32 drinkLimit = + HEART_MAX_ENERGY[Cmn::ItemMgr::GetInstance().GetBicHeartNum()]; + // Drinking restores 80% energy - f32 drinkLimit = scHeartMaxEnergy[ItemMgr::GetInstance().GetBicHeartNum()]; drinkLimit *= 0.80f; if (pCyclist->getEnergy() >= drinkLimit) { @@ -113,5 +117,6 @@ TRAMPOLINE_DEF(0x803afb90, 0x803afcb8) { // clang-format on } +} // namespace Item } // namespace Bic } // namespace AP diff --git a/src/hooks/Bsk/checks_Bsk.cpp b/src/Scene/Bsk/checks_Bsk.cpp similarity index 78% rename from src/hooks/Bsk/checks_Bsk.cpp rename to src/Scene/Bsk/checks_Bsk.cpp index 68752a1..7c8b8d5 100644 --- a/src/hooks/Bsk/checks_Bsk.cpp +++ b/src/Scene/Bsk/checks_Bsk.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Bsk { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Bsk { * ******************************************************************************/ - +} // namespace Check } // namespace Bsk } // namespace AP \ No newline at end of file diff --git a/src/hooks/Bsk/items_Bsk.cpp b/src/Scene/Bsk/items_Bsk.cpp similarity index 84% rename from src/hooks/Bsk/items_Bsk.cpp rename to src/Scene/Bsk/items_Bsk.cpp index a13a2fb..d8c690e 100644 --- a/src/hooks/Bsk/items_Bsk.cpp +++ b/src/Scene/Bsk/items_Bsk.cpp @@ -1,11 +1,11 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { +namespace Item { namespace Bsk { //! Timer frame-rate (frames/timer sec) @@ -16,7 +16,7 @@ static const u32 TIMER_RATE = 60; * Basketball (3-Point Contest) * ******************************************************************************/ -namespace Pt3 { +namespace Pt { //! Number of basketballs in each rack static const u32 RACK_BALL_NUM = 5; @@ -29,8 +29,8 @@ static const u32 RACK_BALL_NUM = 5; void InitTimer(Sp2::Bsk::Sequence3pt* pSequence) { ASSERT(pSequence != nullptr); - u32 timerNum = ItemMgr::GetInstance().GetBsk3ptTimerNum(); - u32 timerSec = timerNum * ItemMgr::BSK_3PT_TIMER_VALUE; + u32 timerNum = Cmn::ItemMgr::GetInstance().GetBsk3ptTimerNum(); + u32 timerSec = timerNum * Cmn::ItemMgr::BSK_3PT_TIMER_VALUE; pSequence->getMainLyt()->setTimer(timerSec, TIMER_RATE); } @@ -66,7 +66,7 @@ void InitBallType(Sp2::Bsk::Ball* pBall, s32 id) { : Sp2::Bsk::Ball::EType_Regular; // Bonus balls locked behind the item - if (!ItemMgr::GetInstance().IsBsk3ptBonus()) { + if (!Cmn::ItemMgr::GetInstance().IsBsk3ptBonus()) { type = Sp2::Bsk::Ball::EType_Regular; } @@ -89,7 +89,7 @@ TRAMPOLINE_DEF(0x80522CFC, 0x80522D10) { // clang-format on } -} // namespace Pt3 +} // namespace Pt /****************************************************************************** * @@ -106,8 +106,8 @@ namespace Vs { void InitTimer(Sp2::Bsk::SequenceVs* pSequence) { ASSERT(pSequence != nullptr); - u32 timerNum = ItemMgr::GetInstance().GetBskVsTimerNum(); - u32 timerSec = timerNum * ItemMgr::BSK_VS_TIMER_VALUE; + u32 timerNum = Cmn::ItemMgr::GetInstance().GetBskVsTimerNum(); + u32 timerSec = timerNum * Cmn::ItemMgr::BSK_VS_TIMER_VALUE; pSequence->getMainLyt()->setTimer(timerSec, TIMER_RATE); } @@ -128,7 +128,7 @@ TRAMPOLINE_DEF(0x80507C74, 0x80507C78) { } bool HasPassUnlocked() { - return ItemMgr::GetInstance().IsBskVsPass(); + return Cmn::ItemMgr::GetInstance().IsBskVsPass(); } TRAMPOLINE_DEF(0x8052ce98, 0x8052ce9c) { @@ -157,7 +157,7 @@ TRAMPOLINE_DEF(0x8052ce98, 0x8052ce9c) { } bool Has3ptUnlocked() { - return ItemMgr::GetInstance().IsBskVs3pt(); + return Cmn::ItemMgr::GetInstance().IsBskVs3pt(); } TRAMPOLINE_DEF(0x8050685C, 0x80506860) { @@ -188,16 +188,16 @@ TRAMPOLINE_DEF(0x8050685C, 0x80506860) { * @brief Unlocks Pickup Game dunking */ bool HasDunkUnlocked() { - return ItemMgr::GetInstance().IsBskVsDunk(); + return Cmn::ItemMgr::GetInstance().IsBskVsDunk(); } /** * @brief HasDunkUnlocked trampolines - * - * To disable dunks, function must always return -1. Two return statements exist that - * normally return 1 and 0, so both are patched individually here. + * + * To disable dunks, function must always return -1. Two return statements exist + * that normally return 1 and 0, so both are patched individually here. */ -TRAMPOLINE_DEF(0x80501f2c, 0x80501f30) { +TRAMPOLINE_DEF(0x80501f2c, 0x80501f30){ // clang-format off TRAMPOLINE_BEGIN @@ -240,4 +240,5 @@ TRAMPOLINE_DEF(0x80501f5c, 0x80501f60) { } // namespace Vs } // namespace Bsk +} // namespace Item } // namespace AP diff --git a/src/hooks/Bwl/checks_Bwl.cpp b/src/Scene/Bwl/checks_Bwl.cpp similarity index 72% rename from src/hooks/Bwl/checks_Bwl.cpp rename to src/Scene/Bwl/checks_Bwl.cpp index 6c8e85e..2f2375c 100644 --- a/src/hooks/Bwl/checks_Bwl.cpp +++ b/src/Scene/Bwl/checks_Bwl.cpp @@ -1,27 +1,28 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Bwl { -namespace { -namespace Std { +namespace Check { /****************************************************************************** * * Bowling Standard Game * ******************************************************************************/ +namespace Std { void SetBowlingStrikeCheck() { - bool hasCheck = CheckMgr::GetInstance().GetCheckState( + bool hasCheck = Cmn::CheckMgr::GetInstance().GetCheckState( CHECK_BOWLING_STANDARD_FIRST_STRIKE); if (hasCheck) return; - CheckMgr::GetInstance().GiveCheckItem(CHECK_BOWLING_STANDARD_FIRST_STRIKE); + Cmn::CheckMgr::GetInstance().GiveCheckItem( + CHECK_BOWLING_STANDARD_FIRST_STRIKE); } TRAMPOLINE_DEF(0x804ece1c, 0x804ece20) { @@ -38,6 +39,7 @@ TRAMPOLINE_DEF(0x804ece1c, 0x804ece20) { } } // namespace Std -} // namespace + +} // namespace Check } // namespace Bwl } // namespace AP \ No newline at end of file diff --git a/src/hooks/Bwl/cosmetics_Bwl.cpp b/src/Scene/Bwl/cosmetics_Bwl.cpp similarity index 98% rename from src/hooks/Bwl/cosmetics_Bwl.cpp rename to src/Scene/Bwl/cosmetics_Bwl.cpp index 459e52b..43da50e 100644 --- a/src/hooks/Bwl/cosmetics_Bwl.cpp +++ b/src/Scene/Bwl/cosmetics_Bwl.cpp @@ -1,8 +1,4 @@ -#include - -#include "core/CosmeticMgr.h" -#include "hooks/trampoline.h" - +#include "trampoline.h" #include #include #include diff --git a/src/hooks/Bwl/items_Bwl.cpp b/src/Scene/Bwl/items_Bwl.cpp similarity index 85% rename from src/hooks/Bwl/items_Bwl.cpp rename to src/Scene/Bwl/items_Bwl.cpp index 479bed0..4db877b 100644 --- a/src/hooks/Bwl/items_Bwl.cpp +++ b/src/Scene/Bwl/items_Bwl.cpp @@ -1,18 +1,19 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Bwl { +namespace Item { /****************************************************************************** * * Bowling Standard Game * ******************************************************************************/ +namespace Std { /** * @brief Determines if the player can move in bowling @@ -23,17 +24,17 @@ bool BwlCheckMoveState() { switch (sequence) { case Sp2::Cmn::ESeq_Bwl_Std: { - unlocked = ItemMgr::GetInstance().IsBwlStdMove(); + unlocked = Cmn::ItemMgr::GetInstance().IsBwlStdMove(); break; } case Sp2::Cmn::ESeq_Bwl_100: { - unlocked = ItemMgr::GetInstance().IsBwl100Move(); + unlocked = Cmn::ItemMgr::GetInstance().IsBwl100Move(); break; } case Sp2::Cmn::ESeq_Bwl_Wal: { - unlocked = ItemMgr::GetInstance().IsBwlWalMove(); + unlocked = Cmn::ItemMgr::GetInstance().IsBwlWalMove(); break; } @@ -95,17 +96,17 @@ bool BwlCheckTurnState() { switch (sequence) { case Sp2::Cmn::ESeq_Bwl_Std: { - unlocked = ItemMgr::GetInstance().IsBwlStdTurn(); + unlocked = Cmn::ItemMgr::GetInstance().IsBwlStdTurn(); break; } case Sp2::Cmn::ESeq_Bwl_100: { - unlocked = ItemMgr::GetInstance().IsBwl100Turn(); + unlocked = Cmn::ItemMgr::GetInstance().IsBwl100Turn(); break; } case Sp2::Cmn::ESeq_Bwl_Wal: { - unlocked = ItemMgr::GetInstance().IsBwlWalTurn(); + unlocked = Cmn::ItemMgr::GetInstance().IsBwlWalTurn(); break; } @@ -156,6 +157,8 @@ TRAMPOLINE_DEF(0x804ea658, 0x804ea65C) { TRAMPOLINE_END blr // clang-format on +} + } // namespace Std /****************************************************************************** @@ -163,12 +166,13 @@ TRAMPOLINE_DEF(0x804ea658, 0x804ea65C) { * Bowling 100-Pin Game * ******************************************************************************/ +namespace Pin { /** * @brief Determines if the player can press the secret strike button */ bool BwlSecretStrike() { - return ItemMgr::GetInstance().IsBwl100SecretBtn(); + return Cmn::ItemMgr::GetInstance().IsBwl100SecretBtn(); } /** @@ -194,7 +198,10 @@ TRAMPOLINE_DEF(0x804f0058, 0x804f0068) { TRAMPOLINE_END blr // clang-format on -} // namespace 100 +} + +} // namespace Pin +} // namespace Item } // namespace Bwl } // namespace AP diff --git a/src/hooks/Can/checks_Can.cpp b/src/Scene/Can/checks_Can.cpp similarity index 77% rename from src/hooks/Can/checks_Can.cpp rename to src/Scene/Can/checks_Can.cpp index 8e8bdae..eab0676 100644 --- a/src/hooks/Can/checks_Can.cpp +++ b/src/Scene/Can/checks_Can.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Can { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Can { * ******************************************************************************/ - +} // namespace Check } // namespace Can } // namespace AP \ No newline at end of file diff --git a/src/hooks/Can/items_Can.cpp b/src/Scene/Can/items_Can.cpp similarity index 80% rename from src/hooks/Can/items_Can.cpp rename to src/Scene/Can/items_Can.cpp index e0ad718..46f7bd4 100644 --- a/src/hooks/Can/items_Can.cpp +++ b/src/Scene/Can/items_Can.cpp @@ -1,14 +1,12 @@ - - -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Can { +namespace Item { /****************************************************************************** * @@ -37,10 +35,10 @@ int CanSetTimer(int difficulty) { difficultyTimer = 60; } - float timer = - (float)difficultyTimer / - (ItemMgr::CAN_TIMER_COUNT - ItemMgr::GetInstance().GetCanTimerNum()); - return timer; + u32 divide = Cmn::ItemMgr::CAN_TIMER_COUNT - + Cmn::ItemMgr::GetInstance().GetCanTimerNum(); + + return (float)difficultyTimer / divide; } /** @@ -61,5 +59,6 @@ TRAMPOLINE_DEF(0x804af188, 0x804af1e0) { // clang-format on } +} // namespace Item } // namespace Can } // namespace AP diff --git a/src/hooks/Cmn/checks_Cmn.cpp b/src/Scene/Cmn/checks_Cmn.cpp similarity index 95% rename from src/hooks/Cmn/checks_Cmn.cpp rename to src/Scene/Cmn/checks_Cmn.cpp index 92a299c..fb25620 100644 --- a/src/hooks/Cmn/checks_Cmn.cpp +++ b/src/Scene/Cmn/checks_Cmn.cpp @@ -1,5 +1,5 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include diff --git a/src/hooks/Cmn/cosmetics_Cmn.cpp b/src/Scene/Cmn/cosmetics_Cmn.cpp similarity index 97% rename from src/hooks/Cmn/cosmetics_Cmn.cpp rename to src/Scene/Cmn/cosmetics_Cmn.cpp index c4e0484..a5ed569 100644 --- a/src/hooks/Cmn/cosmetics_Cmn.cpp +++ b/src/Scene/Cmn/cosmetics_Cmn.cpp @@ -1,10 +1,7 @@ -#include - -#include "core/CosmeticMgr.h" -#include "core/ItemMgr.h" -#include "hooks/Swf/items_Swf.h" -#include "hooks/trampoline.h" - +#include "Cmn/CosmeticMgr.h" +#include "Cmn/ItemMgr.h" +#include "Scene/Swf/items_Swf.h" +#include "trampoline.h" #include #include #include @@ -239,7 +236,7 @@ TRAMPOLINE_DEF(0x801f546c, 0x801f5514){ /** * @brief InterceptFavoriteColorHat trampoline */ -TRAMPOLINE_DEF(0x801032c4, 0x801032c8) { +TRAMPOLINE_DEF(0x801032c4, 0x801032c8){ // clang-format off TRAMPOLINE_BEGIN diff --git a/src/hooks/Cmn/items_Cmn.cpp b/src/Scene/Cmn/items_Cmn.cpp similarity index 90% rename from src/hooks/Cmn/items_Cmn.cpp rename to src/Scene/Cmn/items_Cmn.cpp index 3eb5895..ce1443f 100644 --- a/src/hooks/Cmn/items_Cmn.cpp +++ b/src/Scene/Cmn/items_Cmn.cpp @@ -1,9 +1,7 @@ -#include - -#include "core/CosmeticMgr.h" -#include "core/ItemMgr.h" -#include "hooks/Swf/items_Swf.h" -#include "hooks/trampoline.h" +#include "Cmn/CosmeticMgr.h" +#include "Cmn/ItemMgr.h" +#include "Scene/Swf/items_Swf.h" +#include "trampoline.h" #include #include #include @@ -31,7 +29,7 @@ void TryPause() { // Pausing is disabled in Speed Slice while objects are falling if (isSwfPrc && !ItemMgr::GetInstance().IsSwfPrcPause() && - Swf::PrcIsObjFalling()) { + Swf::Item::PrcIsObjFalling()) { return; } @@ -50,7 +48,7 @@ bool TryHomeButton() { // Home menu is disabled in Speed Slice while objects are falling if (isSwfPrc && !ItemMgr::GetInstance().IsSwfPrcPause() && - Swf::PrcIsObjFalling()) { + Swf::Item::PrcIsObjFalling()) { return false; } diff --git a/src/scene/DebugRootScene/RootPage.cpp b/src/Scene/DebugRoot/RootPage.cpp similarity index 97% rename from src/scene/DebugRootScene/RootPage.cpp rename to src/Scene/DebugRoot/RootPage.cpp index 65ceabe..90838d7 100644 --- a/src/scene/DebugRootScene/RootPage.cpp +++ b/src/Scene/DebugRoot/RootPage.cpp @@ -1,4 +1,4 @@ -#include "scene/DebugRootScene/RootPage.h" +#include "scene/DebugRoot/RootPage.h" #include diff --git a/src/scene/DebugRootScene/RootPage.h b/src/Scene/DebugRoot/RootPage.h similarity index 95% rename from src/scene/DebugRootScene/RootPage.h rename to src/Scene/DebugRoot/RootPage.h index f9d7636..b83e1df 100644 --- a/src/scene/DebugRootScene/RootPage.h +++ b/src/Scene/DebugRoot/RootPage.h @@ -1,7 +1,7 @@ #ifndef APCLIENT_SCENE_DEBUGROOTSCENE_ROOT_PAGE_H #define APCLIENT_SCENE_DEBUGROOTSCENE_ROOT_PAGE_H -#include "core/const.h" -#include "scene/DebugRootScene/SceneSelectPage.h" +#include "const.h" +#include "scene/DebugRoot/SceneSelectPage.h" #include diff --git a/src/scene/DebugRootScene/Scene.cpp b/src/Scene/DebugRoot/Scene.cpp similarity index 98% rename from src/scene/DebugRootScene/Scene.cpp rename to src/Scene/DebugRoot/Scene.cpp index 8bde994..598f2b8 100644 --- a/src/scene/DebugRootScene/Scene.cpp +++ b/src/Scene/DebugRoot/Scene.cpp @@ -1,4 +1,4 @@ -#include "scene/DebugRootScene/Scene.h" +#include "scene/DebugRoot/Scene.h" #include diff --git a/src/scene/DebugRootScene/Scene.h b/src/Scene/DebugRoot/Scene.h similarity index 94% rename from src/scene/DebugRootScene/Scene.h rename to src/Scene/DebugRoot/Scene.h index a5deb12..b83353f 100644 --- a/src/scene/DebugRootScene/Scene.h +++ b/src/Scene/DebugRoot/Scene.h @@ -1,7 +1,7 @@ #ifndef APCLIENT_SCENE_DEBUGROOTSCENE_SCENE_H #define APCLIENT_SCENE_DEBUGROOTSCENE_SCENE_H -#include "core/const.h" -#include "scene/DebugRootScene/RootPage.h" +#include "const.h" +#include "scene/DebugRoot/RootPage.h" #include diff --git a/src/scene/DebugRootScene/SceneSelectPage.cpp b/src/Scene/DebugRoot/SceneSelectPage.cpp similarity index 97% rename from src/scene/DebugRootScene/SceneSelectPage.cpp rename to src/Scene/DebugRoot/SceneSelectPage.cpp index 37f721d..b9e2952 100644 --- a/src/scene/DebugRootScene/SceneSelectPage.cpp +++ b/src/Scene/DebugRoot/SceneSelectPage.cpp @@ -1,4 +1,4 @@ -#include "scene/DebugRootScene/SceneSelectPage.h" +#include "scene/DebugRoot/SceneSelectPage.h" #include diff --git a/src/scene/DebugRootScene/SceneSelectPage.h b/src/Scene/DebugRoot/SceneSelectPage.h similarity index 95% rename from src/scene/DebugRootScene/SceneSelectPage.h rename to src/Scene/DebugRoot/SceneSelectPage.h index 9c974f5..fff2188 100644 --- a/src/scene/DebugRootScene/SceneSelectPage.h +++ b/src/Scene/DebugRoot/SceneSelectPage.h @@ -2,7 +2,7 @@ #define APCLIENT_SCENE_DEBUGROOTSCENE_SCENE_SELECT_PAGE_H #include -#include "scene/DebugRootScene/SeqSelectPage.h" +#include "scene/DebugRoot/SeqSelectPage.h" #include diff --git a/src/scene/DebugRootScene/SeqSelectPage.cpp b/src/Scene/DebugRoot/SeqSelectPage.cpp similarity index 98% rename from src/scene/DebugRootScene/SeqSelectPage.cpp rename to src/Scene/DebugRoot/SeqSelectPage.cpp index 965ada0..d13be97 100644 --- a/src/scene/DebugRootScene/SeqSelectPage.cpp +++ b/src/Scene/DebugRoot/SeqSelectPage.cpp @@ -1,6 +1,6 @@ -#include "scene/DebugRootScene/SeqSelectPage.h" +#include "scene/DebugRoot/SeqSelectPage.h" -#include "scene/DebugRootScene/SceneSelectPage.h" +#include "scene/DebugRoot/SceneSelectPage.h" #include #include @@ -136,12 +136,12 @@ void SeqSelectPage::SetNextScene(s32 scene) { void SeqSelectPage::UserDraw() { DebugPage::UserDraw(); - K_ASSERT(mNextScene >= 0); + ASSERT(mNextScene >= 0); const char* pSceneName = kiwi::SceneCreator::GetInstance().GetSceneName(mNextScene); - K_ASSERT_PTR(pSceneName); + ASSERT_PTR(pSceneName); kiwi::Text(pSceneName) .SetTextColor(kiwi::Color::CYAN) @@ -182,7 +182,7 @@ kiwi::EDebugMenuResult SeqSelectPage::State_Select_calc() { * @return Result of actions */ kiwi::EDebugMenuResult SeqSelectPage::State_Decide_calc() { - K_ASSERT(mNextScene >= 0); + ASSERT(mNextScene >= 0); if (mStateMachine.IsFirstStep()) { Sp2::Snd::startSe(SE_CMN_DECIDE_01); diff --git a/src/scene/DebugRootScene/SeqSelectPage.h b/src/Scene/DebugRoot/SeqSelectPage.h similarity index 100% rename from src/scene/DebugRootScene/SeqSelectPage.h rename to src/Scene/DebugRoot/SeqSelectPage.h diff --git a/src/hooks/Dgl/checks_Dgl.cpp b/src/Scene/Dgl/checks_Dgl.cpp similarity index 77% rename from src/hooks/Dgl/checks_Dgl.cpp rename to src/Scene/Dgl/checks_Dgl.cpp index 1fd485e..f9e24e4 100644 --- a/src/hooks/Dgl/checks_Dgl.cpp +++ b/src/Scene/Dgl/checks_Dgl.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Dgl { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Dgl { * ******************************************************************************/ - +} // namespace Check } // namespace Dgl } // namespace AP \ No newline at end of file diff --git a/src/hooks/Dgl/items_Dgl.cpp b/src/Scene/Dgl/items_Dgl.cpp similarity index 83% rename from src/hooks/Dgl/items_Dgl.cpp rename to src/Scene/Dgl/items_Dgl.cpp index 1639eeb..fa44d2d 100644 --- a/src/hooks/Dgl/items_Dgl.cpp +++ b/src/Scene/Dgl/items_Dgl.cpp @@ -1,6 +1,5 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include @@ -8,6 +7,7 @@ namespace AP { namespace Dgl { +namespace Item { /****************************************************************************** * @@ -15,7 +15,7 @@ namespace Dgl { * ******************************************************************************/ void DglSetBlindFlag(bool hold2) { - if (hold2 || !ItemMgr::GetInstance().IsDglHUD()) { + if (hold2 || !Cmn::ItemMgr::GetInstance().IsDglHUD()) { RP_GET_INSTANCE(Sp2::Cmn::StaticMem)->setVariable(3, 1, false); } @@ -38,5 +38,6 @@ TRAMPOLINE_DEF(0x802287d4, 0x802287e8) { // clang-format on } +} // namespace Item } // namespace Dgl } // namespace AP diff --git a/src/hooks/Fld/checks_Fld.cpp b/src/Scene/Fld/checks_Fld.cpp similarity index 77% rename from src/hooks/Fld/checks_Fld.cpp rename to src/Scene/Fld/checks_Fld.cpp index 0fad52b..6969d31 100644 --- a/src/hooks/Fld/checks_Fld.cpp +++ b/src/Scene/Fld/checks_Fld.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Fld { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Fld { * ******************************************************************************/ - +} // namespace Check } // namespace Fld } // namespace AP \ No newline at end of file diff --git a/src/hooks/Fld/items_Fld.cpp b/src/Scene/Fld/items_Fld.cpp similarity index 78% rename from src/hooks/Fld/items_Fld.cpp rename to src/Scene/Fld/items_Fld.cpp index 35c1cc2..c71402d 100644 --- a/src/hooks/Fld/items_Fld.cpp +++ b/src/Scene/Fld/items_Fld.cpp @@ -1,6 +1,5 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include @@ -8,6 +7,7 @@ namespace AP { namespace Fld { +namespace Item { /****************************************************************************** * @@ -16,8 +16,10 @@ namespace Fld { ******************************************************************************/ u32 FldA2Disable(u32 inputs) { - if (!ItemMgr::GetInstance().IsFldSecretPop()) return 0; - else return inputs; + if (!Cmn::ItemMgr::GetInstance().IsFldSecretPop()) + return 0; + else + return inputs; } /** @@ -41,20 +43,20 @@ TRAMPOLINE_DEF(0x805ee79c, 0x805ee7a0) { * @brief Sets number of frisbee throws */ int FldSetThrows() { - return ItemMgr::GetInstance().GetFldThrowNum(); + return Cmn::ItemMgr::GetInstance().GetFldThrowNum(); } /** * @brief Ermmmmmmmm */ int FldSetThrowsBackwards() { - return 10 - ItemMgr::GetInstance().GetFldThrowNum(); + return 10 - Cmn::ItemMgr::GetInstance().GetFldThrowNum(); } /** * @brief FldSetThrows trampoline */ -TRAMPOLINE_DEF(0x805deda0, 0x805deda4) { +TRAMPOLINE_DEF(0x805deda0, 0x805deda4){ // clang-format off TRAMPOLINE_BEGIN @@ -88,5 +90,6 @@ TRAMPOLINE_DEF(0x805dc458, 0x805dc460) { // clang-format on } +} // namespace Item } // namespace Fld } // namespace AP \ No newline at end of file diff --git a/src/hooks/Glf/checks_Glf.cpp b/src/Scene/Glf/checks_Glf.cpp similarity index 83% rename from src/hooks/Glf/checks_Glf.cpp rename to src/Scene/Glf/checks_Glf.cpp index 3a393df..9b07c90 100644 --- a/src/hooks/Glf/checks_Glf.cpp +++ b/src/Scene/Glf/checks_Glf.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Glf { -namespace { +namespace Check { /****************************************************************************** * @@ -15,12 +15,12 @@ namespace { ******************************************************************************/ void SetGolfHoleComplete(int holeIdx) { - bool hasCheck = CheckMgr::GetInstance().GetCheckState( + bool hasCheck = Cmn::CheckMgr::GetInstance().GetCheckState( CheckID(CHECK_GOLF_COMPLETE_HOLE_1 + holeIdx)); if (hasCheck) return; - CheckMgr::GetInstance().GiveCheckItem( + Cmn::CheckMgr::GetInstance().GiveCheckItem( CheckID(CHECK_GOLF_COMPLETE_HOLE_1 + holeIdx)); } @@ -55,6 +55,6 @@ TRAMPOLINE_DEF(0x804069f8, 0x804069fc) { // clang-format on } -} // namespace +} // namespace Check } // namespace Glf } // namespace AP \ No newline at end of file diff --git a/src/hooks/Glf/items_Glf.cpp b/src/Scene/Glf/items_Glf.cpp similarity index 84% rename from src/hooks/Glf/items_Glf.cpp rename to src/Scene/Glf/items_Glf.cpp index a51e88e..30fb638 100644 --- a/src/hooks/Glf/items_Glf.cpp +++ b/src/Scene/Glf/items_Glf.cpp @@ -1,6 +1,5 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include @@ -8,6 +7,7 @@ namespace AP { namespace Glf { +namespace Item { /****************************************************************************** * @@ -16,7 +16,7 @@ namespace Glf { ******************************************************************************/ int GlfClubUp(int currentClubIdx) { for (int i = currentClubIdx - 1; i >= 0; i--) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { return i; } } @@ -42,7 +42,7 @@ TRAMPOLINE_DEF(0x8040945c, 0x80409460) { int GlfClubDown(int currentClubIdx) { for (int i = currentClubIdx + 1; i <= 7; i++) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { return i; } } @@ -69,8 +69,8 @@ TRAMPOLINE_DEF(0x804093a0, 0x804093a4) { int GetMaxClubID() { int maxClubID = 0; - for (int i = 0; i < ItemMgr::GLF_CLUB_COUNT - 1; i++) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + for (int i = 0; i < Cmn::ItemMgr::GLF_CLUB_COUNT - 1; i++) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { maxClubID = i; } } @@ -81,8 +81,8 @@ int GetMaxClubID() { int GetMinClubID() { int minClubID = 7; - for (int i = 0; i <= ItemMgr::GLF_CLUB_COUNT - 1; i++) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + for (int i = 0; i <= Cmn::ItemMgr::GLF_CLUB_COUNT - 1; i++) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { minClubID = i; } } @@ -94,7 +94,7 @@ int GetNextClubUp(int currentClubIdx) { int nextClubIdx = currentClubIdx; for (int i = currentClubIdx - 1; i >= 0; i--) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { nextClubIdx = i; break; } @@ -103,7 +103,7 @@ int GetNextClubUp(int currentClubIdx) { // if no club up, go down if (nextClubIdx == currentClubIdx) { for (int i = currentClubIdx; i < 7; i++) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { nextClubIdx = i; break; } @@ -117,7 +117,7 @@ int GetNextClubDown(int currentClubIdx) { int nextClubIdx = currentClubIdx; for (int i = currentClubIdx + 1; i <= 7; i++) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { nextClubIdx = i; break; } @@ -126,7 +126,7 @@ int GetNextClubDown(int currentClubIdx) { // if no club down, go up if (nextClubIdx == currentClubIdx) { for (int i = currentClubIdx; i >= 0; i--) { - if (ItemMgr::GetInstance().IsGlfClubUnlock(i)) { + if (Cmn::ItemMgr::GetInstance().IsGlfClubUnlock(i)) { nextClubIdx = i; break; } @@ -217,7 +217,7 @@ TRAMPOLINE_DEF(0x8040924c, 0x80409250) { } void GlfSetBlindFlag(bool hold2) { - if (hold2 || !ItemMgr::GetInstance().IsGlfHUD()) { + if (hold2 || !Cmn::ItemMgr::GetInstance().IsGlfHUD()) { RP_GET_INSTANCE(Sp2::Cmn::StaticMem)->setVariable(3, 1, false); } @@ -241,7 +241,7 @@ TRAMPOLINE_DEF(0x80406a1c, 0x80406a30){ } u32 GlfDisableZoom(u32 input) { - if (!ItemMgr::GetInstance().IsGlfViewLow()) + if (!Cmn::ItemMgr::GetInstance().IsGlfViewLow()) return 0; else return input; @@ -265,7 +265,7 @@ TRAMPOLINE_DEF(0x803facdc, 0x803face0){ } u32 GlfDisableTopo(u32 input) { - if (!ItemMgr::GetInstance().IsGlfViewSlope()) + if (!Cmn::ItemMgr::GetInstance().IsGlfViewSlope()) return 0; else return input; @@ -289,7 +289,7 @@ TRAMPOLINE_DEF(0x803fac64, 0x803fac68) { } bool GlfDisableTurn() { - return ItemMgr::GetInstance().IsGlfTurn(); + return Cmn::ItemMgr::GetInstance().IsGlfTurn(); } /** @@ -323,7 +323,7 @@ TRAMPOLINE_DEF(0x803fac54, 0x803fac58) { } bool GlfHasBackSpin() { - return ItemMgr::GetInstance().IsGlfSpin(); + return Cmn::ItemMgr::GetInstance().IsGlfSpin(); } /** @@ -358,5 +358,6 @@ TRAMPOLINE_DEF(0x80414068, 0x80414088) { // clang-format on } +} // namespace Item } // namespace Glf } // namespace AP diff --git a/src/hooks/Jsk/checks_Jsk.cpp b/src/Scene/Jsk/checks_Jsk.cpp similarity index 77% rename from src/hooks/Jsk/checks_Jsk.cpp rename to src/Scene/Jsk/checks_Jsk.cpp index 08f55e5..6300f64 100644 --- a/src/hooks/Jsk/checks_Jsk.cpp +++ b/src/Scene/Jsk/checks_Jsk.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Jsk { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Jsk { * ******************************************************************************/ - +} // namespace Check } // namespace Jsk } // namespace AP \ No newline at end of file diff --git a/src/hooks/Jsk/checks_Wkb.cpp b/src/Scene/Jsk/checks_Wkb.cpp similarity index 77% rename from src/hooks/Jsk/checks_Wkb.cpp rename to src/Scene/Jsk/checks_Wkb.cpp index 3df77e5..888f702 100644 --- a/src/hooks/Jsk/checks_Wkb.cpp +++ b/src/Scene/Jsk/checks_Wkb.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Wkb { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Wkb { * ******************************************************************************/ - +} // namespace Check } // namespace Wkb } // namespace AP \ No newline at end of file diff --git a/src/hooks/Jsk/items_Jsk.cpp b/src/Scene/Jsk/items_Jsk.cpp similarity index 81% rename from src/hooks/Jsk/items_Jsk.cpp rename to src/Scene/Jsk/items_Jsk.cpp index 26def4a..fda1df3 100644 --- a/src/hooks/Jsk/items_Jsk.cpp +++ b/src/Scene/Jsk/items_Jsk.cpp @@ -1,12 +1,12 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - -#include +#include "Cmn/ItemMgr.h" +#include "trampoline.h" +#include #include namespace AP { namespace Jsk { +namespace Item { /****************************************************************************** * @@ -19,7 +19,7 @@ namespace Jsk { * */ int JskSetTimer() { - return ItemMgr::GetInstance().GetJskFreeTimerNum() * 60; + return Cmn::ItemMgr::GetInstance().GetJskFreeTimerNum() * 60; } /** @@ -42,13 +42,13 @@ TRAMPOLINE_DEF(0x8058321c, 0x80583220) { * */ int JskSetBalloons() { - return ItemMgr::GetInstance().GetJskFreeTimerNum() * 12; + return Cmn::ItemMgr::GetInstance().GetJskFreeTimerNum() * 12; } /** * @brief JskSetBalloons trampoline */ -TRAMPOLINE_DEF(0x80581eb0, 0x80581eb4) { +TRAMPOLINE_DEF(0x80581eb0, 0x80581eb4){ // clang-format off TRAMPOLINE_BEGIN @@ -74,13 +74,13 @@ TRAMPOLINE_DEF(0x8059ecc4, 0x8059ecc8) { * @brief Unlocks Boosting in Power Cruising */ bool JskSetBoost() { - return ItemMgr::GetInstance().IsJskBoost(); + return Cmn::ItemMgr::GetInstance().IsJskBoost(); } /** * @brief JskSetBoost trampoline */ -TRAMPOLINE_DEF(0x8059717c, 0x80597180) { +TRAMPOLINE_DEF(0x8059717c, 0x80597180){ // clang-format off TRAMPOLINE_BEGIN @@ -114,13 +114,13 @@ u32 JskUndoBonus(u32 flags) { * @brief Unlocks 2x rings in Power Cruising */ bool JskSetBonus() { - return ItemMgr::GetInstance().IsJsk2xRing(); + return Cmn::ItemMgr::GetInstance().IsJsk2xRing(); } /** * @brief JskSetBonus trampoline */ -TRAMPOLINE_DEF(0x8059164c, 0x80591650) { +TRAMPOLINE_DEF(0x8059164c, 0x80591650){ // clang-format off TRAMPOLINE_BEGIN @@ -150,7 +150,7 @@ TRAMPOLINE_DEF(0x8059164c, 0x80591650) { * @brief Sets ring timer in Power Cruising */ f32 JskSetRingTimer() { - int timerCount = ItemMgr::GetInstance().GetJskRingTimerNum(); + int timerCount = Cmn::ItemMgr::GetInstance().GetJskRingTimerNum(); f32 timerNums[] = {(f32)3.0, (f32)7.0, (f32)11.0}; return timerNums[timerCount]; } @@ -170,5 +170,6 @@ TRAMPOLINE_DEF(0x805914a8, 0x805914ac) { // clang-format on } +} // namespace Item } // namespace Jsk } // namespace AP diff --git a/src/hooks/Jsk/items_Wkb.cpp b/src/Scene/Jsk/items_Wkb.cpp similarity index 78% rename from src/hooks/Jsk/items_Wkb.cpp rename to src/Scene/Jsk/items_Wkb.cpp index c6ae821..e1e856e 100644 --- a/src/hooks/Jsk/items_Wkb.cpp +++ b/src/Scene/Jsk/items_Wkb.cpp @@ -1,12 +1,12 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Wkb { +namespace Item { /****************************************************************************** * @@ -22,8 +22,8 @@ namespace Wkb { void WkbSetTimer(Sp2::Jsk::IslandSeq* pSequence) { ASSERT(pSequence != nullptr); - u32 timerNum = ItemMgr::GetInstance().GetWkbTimerNum(); - pSequence->setTimeRemain(timerNum * ItemMgr::WKB_TIMER_VALUE); + u32 timerNum = Cmn::ItemMgr::GetInstance().GetWkbTimerNum(); + pSequence->setTimeRemain(timerNum * Cmn::ItemMgr::WKB_TIMER_VALUE); } /** @@ -48,12 +48,13 @@ TRAMPOLINE_DEF(0x8058329C, 0x805832A0) { // * @param id Stage ID // */ // Sp2::Cmn::EUnlockState SglGetStageState(UNKWORD, UNKWORD, u32 id) { -// bool unlock = ItemMgr::GetInstance().IsSwfSglStageUnlock(id); +// bool unlock = Cmn::ItemMgr::GetInstance().IsSwfSglStageUnlock(id); // return unlock ? Sp2::Cmn::EUnlockState_Unlocked // : Sp2::Cmn::EUnlockState_Locked; // } // KM_BRANCH(0x802E4848, SglGetStageState); +} // namespace Item } // namespace Wkb } // namespace AP diff --git a/src/hooks/MiiSelect/items_MiiSelect.cpp b/src/Scene/MiiSelect/items_MiiSelect.cpp similarity index 81% rename from src/hooks/MiiSelect/items_MiiSelect.cpp rename to src/Scene/MiiSelect/items_MiiSelect.cpp index 7a0765e..aca5675 100644 --- a/src/hooks/MiiSelect/items_MiiSelect.cpp +++ b/src/Scene/MiiSelect/items_MiiSelect.cpp @@ -1,8 +1,5 @@ -#include - -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include @@ -10,6 +7,7 @@ namespace AP { namespace MiiSelect { +namespace Item { /** * @brief Overrides a stage select button's state based on the AP item unlocks @@ -27,56 +25,56 @@ void InterceptStageBtnState(Sp2::MiiSelect::StageSelectBtnInfo* pBtnInfo, // Scene group determines which sport we are dealing with switch (RP_GET_INSTANCE(Sp2::Cmn::StaticMem)->getSceneGroup()) { case Sp2::Cmn::EGroupID_Jsk: { - state = ItemMgr::GetInstance().IsJskStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsJskStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; } case Sp2::Cmn::EGroupID_Arc: { - state = ItemMgr::GetInstance().IsArcStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsArcStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; } case Sp2::Cmn::EGroupID_Can: { - state = ItemMgr::GetInstance().IsCanStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsCanStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; } case Sp2::Cmn::EGroupID_Wkb: { - state = ItemMgr::GetInstance().IsWkbStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsWkbStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; } case Sp2::Cmn::EGroupID_Pln: { - state = ItemMgr::GetInstance().IsPlnStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsPlnStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; } case Sp2::Cmn::EGroupID_Glf: { - state = ItemMgr::GetInstance().IsGlfStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsGlfStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; } case Sp2::Cmn::EGroupID_Dgl: { - state = ItemMgr::GetInstance().IsDglStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsDglStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; } case Sp2::Cmn::EGroupID_Bic: { - state = ItemMgr::GetInstance().IsBicStageUnlock(idx) + state = Cmn::ItemMgr::GetInstance().IsBicStageUnlock(idx) ? Sp2::MiiSelect::StageSelectBtnInfo::EState_Open : Sp2::MiiSelect::StageSelectBtnInfo::EState_Locked; break; @@ -105,5 +103,6 @@ TRAMPOLINE_DEF(0x8031bda0, 0x8031bdac) { // clang-format on } +} // namespace Item } // namespace MiiSelect } // namespace AP diff --git a/src/hooks/Omk/checks_Omk.cpp b/src/Scene/Omk/checks_Omk.cpp similarity index 77% rename from src/hooks/Omk/checks_Omk.cpp rename to src/Scene/Omk/checks_Omk.cpp index 3130875..e957b79 100644 --- a/src/hooks/Omk/checks_Omk.cpp +++ b/src/Scene/Omk/checks_Omk.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Omk { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Omk { * ******************************************************************************/ - +} // namespace Check } // namespace Omk } // namespace AP \ No newline at end of file diff --git a/src/hooks/Omk/items_Omk.cpp b/src/Scene/Omk/items_Omk.cpp similarity index 77% rename from src/hooks/Omk/items_Omk.cpp rename to src/Scene/Omk/items_Omk.cpp index 8c223eb..a58e7f4 100644 --- a/src/hooks/Omk/items_Omk.cpp +++ b/src/Scene/Omk/items_Omk.cpp @@ -1,12 +1,12 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Omk { +namespace Item { /****************************************************************************** * @@ -14,5 +14,6 @@ namespace Omk { * ******************************************************************************/ +} // namespace Item } // namespace Omk } // namespace AP diff --git a/src/hooks/Pln/checks_Pln.cpp b/src/Scene/Pln/checks_Pln.cpp similarity index 75% rename from src/hooks/Pln/checks_Pln.cpp rename to src/Scene/Pln/checks_Pln.cpp index f9db6e0..8821c70 100644 --- a/src/hooks/Pln/checks_Pln.cpp +++ b/src/Scene/Pln/checks_Pln.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Pln { -namespace { +namespace Check { /****************************************************************************** * @@ -17,16 +17,16 @@ namespace { void SetIPointGrabbed(int totalIPoints) { kiwi::cout << "I Points Grabbed: " << totalIPoints << kiwi::endl; - u32 iGroup = CheckMgr::GetIPointGroupCheckNum(totalIPoints); + u32 iGroup = Cmn::CheckMgr::GetIPointGroupCheckNum(totalIPoints); if (iGroup == 0) return; - bool hasCheck = CheckMgr::GetInstance().GetCheckState( + bool hasCheck = Cmn::CheckMgr::GetInstance().GetCheckState( CheckID(CHECK_ISLAND_FLYOVER_IPOINT_GROUP_1 + iGroup - 1)); if (hasCheck) return; - CheckMgr::GetInstance().GiveCheckItem( + Cmn::CheckMgr::GetInstance().GiveCheckItem( CheckID(CHECK_ISLAND_FLYOVER_IPOINT_GROUP_1 + iGroup - 1)); } @@ -43,6 +43,6 @@ TRAMPOLINE_DEF(0x802619c8, 0x802619cc) { // clang-format on } -} // namespace +} // namespace Check } // namespace Pln } // namespace AP \ No newline at end of file diff --git a/src/hooks/Pln/items_Pln.cpp b/src/Scene/Pln/items_Pln.cpp similarity index 84% rename from src/hooks/Pln/items_Pln.cpp rename to src/Scene/Pln/items_Pln.cpp index c098d40..f2a93e9 100644 --- a/src/hooks/Pln/items_Pln.cpp +++ b/src/Scene/Pln/items_Pln.cpp @@ -1,11 +1,12 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Pln { +namespace Item { /****************************************************************************** * @@ -22,8 +23,8 @@ namespace Pln { void PlnSetTimer(Sp2::Pln::IslandSeq* pSequence) { ASSERT(pSequence != nullptr); - int timerNum = ItemMgr::GetInstance().GetPlnTimerNum(); - pSequence->setTimeRemain(timerNum * ItemMgr::PLN_TIMER_VALUE * 60); + int timerNum = Cmn::ItemMgr::GetInstance().GetPlnTimerNum(); + pSequence->setTimeRemain(timerNum * Cmn::ItemMgr::PLN_TIMER_VALUE * 60); } /** @@ -45,7 +46,7 @@ TRAMPOLINE_DEF(0x80428898, 0x8042889C) { * @brief Unlocks balloons in Island Flyover */ bool PlnSetBalloons() { - return ItemMgr::GetInstance().IsPlnBalloons(); + return Cmn::ItemMgr::GetInstance().IsPlnBalloons(); } /** @@ -81,19 +82,19 @@ u32 PlnSetMisc(u32 currentField) { kiwi::TBitFlag plnUnlocks = currentField; - if (ItemMgr::GetInstance().IsPlnDoubleBlasters()) { + if (Cmn::ItemMgr::GetInstance().IsPlnDoubleBlasters()) { plnUnlocks.SetBit(2); } else { plnUnlocks.ResetBit(2); } - if (ItemMgr::GetInstance().IsPlnNightLights()) { + if (Cmn::ItemMgr::GetInstance().IsPlnNightLights()) { plnUnlocks.SetBit(4); } else { plnUnlocks.ResetBit(4); } - if (ItemMgr::GetInstance().IsPlnTwoSeater()) { + if (Cmn::ItemMgr::GetInstance().IsPlnTwoSeater()) { plnUnlocks.SetBit(5); } else { plnUnlocks.ResetBit(5); @@ -125,7 +126,7 @@ TRAMPOLINE_DEF(0x804455e0, 0x804455e4) { * @brief Unlocks braking in Island Flyover */ bool PlnSetBrake() { - return ItemMgr::GetInstance().IsPlnBrake(); + return Cmn::ItemMgr::GetInstance().IsPlnBrake(); } /** @@ -158,7 +159,7 @@ TRAMPOLINE_DEF(0x80433858, 0x8043385c) { * @brief Unlocks boosting in Island Flyover */ bool PlnSetBoost() { - return ItemMgr::GetInstance().IsPlnBoost(); + return Cmn::ItemMgr::GetInstance().IsPlnBoost(); } /** @@ -210,5 +211,6 @@ TRAMPOLINE_DEF(0x80433f28, 0x80433f2c) { // clang-format on } +} // namespace Item } // namespace Pln } // namespace AP diff --git a/src/hooks/Png/checks_Png.cpp b/src/Scene/Png/checks_Png.cpp similarity index 77% rename from src/hooks/Png/checks_Png.cpp rename to src/Scene/Png/checks_Png.cpp index 4a4ed16..501cddc 100644 --- a/src/hooks/Png/checks_Png.cpp +++ b/src/Scene/Png/checks_Png.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Png { +namespace Check { /****************************************************************************** * @@ -14,6 +14,6 @@ namespace Png { * ******************************************************************************/ - +} // namespace Check } // namespace Png } // namespace AP \ No newline at end of file diff --git a/src/hooks/Png/items_Png.cpp b/src/Scene/Png/items_Png.cpp similarity index 85% rename from src/hooks/Png/items_Png.cpp rename to src/Scene/Png/items_Png.cpp index 1f18e78..35c5c70 100644 --- a/src/hooks/Png/items_Png.cpp +++ b/src/Scene/Png/items_Png.cpp @@ -1,12 +1,12 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" - +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Png { +namespace Item { /****************************************************************************** * @@ -18,7 +18,7 @@ namespace Png { * @brief Unlocks Boosting in Table Tennis */ bool PngCanSmashHit() { - return ItemMgr::GetInstance().IsPngSmash(); + return Cmn::ItemMgr::GetInstance().IsPngSmash(); } /** @@ -43,7 +43,7 @@ TRAMPOLINE_DEF(0x80467470, 0x80467474) { * @brief Unlocks Cans in Table Tennis Return Challenge */ bool PngHasCansUnlocked() { - return ItemMgr::GetInstance().IsPngCans(); + return Cmn::ItemMgr::GetInstance().IsPngCans(); } /** @@ -70,5 +70,6 @@ TRAMPOLINE_DEF(0x80482800, 0x80482804) { // clang-format on } +} // namespace Item } // namespace Png } // namespace AP diff --git a/src/hooks/Swf/checks_Swf.cpp b/src/Scene/Swf/checks_Swf.cpp similarity index 73% rename from src/hooks/Swf/checks_Swf.cpp rename to src/Scene/Swf/checks_Swf.cpp index 10ba543..63fbf9f 100644 --- a/src/hooks/Swf/checks_Swf.cpp +++ b/src/Scene/Swf/checks_Swf.cpp @@ -1,12 +1,12 @@ -#include "core/CheckMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/CheckMgr.h" +#include "trampoline.h" #include #include namespace AP { namespace Swf { -namespace { +namespace Check { /****************************************************************************** * @@ -15,19 +15,23 @@ namespace { ******************************************************************************/ void GetSwordplayFirstWinCheck() { - bool hasCheck = CheckMgr::GetInstance().GetCheckState( + bool hasCheck = Cmn::CheckMgr::GetInstance().GetCheckState( CheckID(CHECK_SWORDPLAY_DUEL_FIRST_WIN)); + if (!hasCheck) { - CheckMgr::GetInstance().GiveCheckItem( + Cmn::CheckMgr::GetInstance().GiveCheckItem( CheckID(CHECK_SWORDPLAY_DUEL_FIRST_WIN)); - hasCheck = CheckMgr::GetInstance().GetCheckState( + + hasCheck = Cmn::CheckMgr::GetInstance().GetCheckState( CheckID(CHECK_SWORDPLAY_DUEL_FIRST_WIN)); + kiwi::cout << "Check: " - << CheckMgr::GetCheckName( + << Cmn::CheckMgr::GetCheckName( CheckID(CHECK_SWORDPLAY_DUEL_FIRST_WIN)) << " has been set to " << hasCheck << kiwi::endl; - } else + } else { kiwi::cout << "Already has check..." << kiwi::endl; + } } TRAMPOLINE_DEF(0x802b1e34, 0x802b1e38) { @@ -44,6 +48,6 @@ TRAMPOLINE_DEF(0x802b1e34, 0x802b1e38) { // clang-format on } -} // namespace +} // namespace Check } // namespace Swf } // namespace AP \ No newline at end of file diff --git a/src/hooks/Swf/items_Swf.cpp b/src/Scene/Swf/items_Swf.cpp similarity index 92% rename from src/hooks/Swf/items_Swf.cpp rename to src/Scene/Swf/items_Swf.cpp index 58fbca3..7a69ac8 100644 --- a/src/hooks/Swf/items_Swf.cpp +++ b/src/Scene/Swf/items_Swf.cpp @@ -1,5 +1,5 @@ -#include "core/ItemMgr.h" -#include "hooks/trampoline.h" +#include "Cmn/ItemMgr.h" +#include "trampoline.h" #include #include #include @@ -8,6 +8,7 @@ namespace AP { namespace Swf { +namespace Item { /****************************************************************************** * @@ -41,12 +42,12 @@ void TryBlock(Sp2::Swf::UserCtrl* pUserCtrl, // Check the appropriate AP item to see if blocking is allowed switch (sequence) { case Sp2::Cmn::ESeq_Swf_Vs: { - unlocked = ItemMgr::GetInstance().IsSwfVsBlock(); + unlocked = Cmn::ItemMgr::GetInstance().IsSwfVsBlock(); break; } case Sp2::Cmn::ESeq_Swf_Sgl: { - unlocked = ItemMgr::GetInstance().IsSwfSglBlock(); + unlocked = Cmn::ItemMgr::GetInstance().IsSwfSglBlock(); break; } @@ -154,7 +155,7 @@ bool PrcIsObjFalling() { void SglSetHeartNum(Sp2::Swf::SglPlayerObject* pPlayer) { ASSERT(pPlayer != nullptr); - int heartNum = ItemMgr::GetInstance().GetSwfSglHeartNum(); + int heartNum = Cmn::ItemMgr::GetInstance().GetSwfSglHeartNum(); pPlayer->setHeartNum(heartNum); } @@ -179,12 +180,13 @@ TRAMPOLINE_DEF(0x8063A010, 0x8063A014){ * @param id Stage ID */ Sp2::Cmn::EUnlockState SglGetStageState(UNKWORD, UNKWORD, u32 id) { - bool unlock = ItemMgr::GetInstance().IsSwfSglStageUnlock(id); + bool unlock = Cmn::ItemMgr::GetInstance().IsSwfSglStageUnlock(id); return unlock ? Sp2::Cmn::EUnlockState_Unlocked : Sp2::Cmn::EUnlockState_Locked; } KM_BRANCH(0x802E4848, SglGetStageState); +} // namespace Item } // namespace Swf } // namespace AP diff --git a/src/hooks/Swf/items_Swf.h b/src/Scene/Swf/items_Swf.h similarity index 66% rename from src/hooks/Swf/items_Swf.h rename to src/Scene/Swf/items_Swf.h index 630a6e1..7e1a7a9 100644 --- a/src/hooks/Swf/items_Swf.h +++ b/src/Scene/Swf/items_Swf.h @@ -1,9 +1,10 @@ -#ifndef APCLIENT_HOOKS_HOOKS_SWF_H -#define APCLIENT_HOOKS_HOOKS_SWF_H +#ifndef APCLIENT_SCENE_SWF_ITEMS_H +#define APCLIENT_SCENE_SWF_ITEMS_H #include namespace AP { namespace Swf { +namespace Item { /** * @brief Tests whether an object is currently falling in Swordplay (Speed @@ -11,6 +12,7 @@ namespace Swf { */ bool PrcIsObjFalling(); +} // namespace Item } // namespace Swf } // namespace AP diff --git a/src/core/checks.h b/src/checks.h similarity index 99% rename from src/core/checks.h rename to src/checks.h index 248ebcc..de0cd31 100644 --- a/src/core/checks.h +++ b/src/checks.h @@ -1,5 +1,5 @@ -#ifndef APCLIENT_CORE_CHECKS_H -#define APCLIENT_CORE_CHECKS_H +#ifndef APCLIENT_CHECKS_H +#define APCLIENT_CHECKS_H #include // clang-format off diff --git a/src/core/const.h b/src/const.h similarity index 95% rename from src/core/const.h rename to src/const.h index 47859e2..290a9a0 100644 --- a/src/core/const.h +++ b/src/const.h @@ -1,9 +1,9 @@ -#ifndef APCLIENT_CORE_CONST_H -#define APCLIENT_CORE_CONST_H +#ifndef APCLIENT_CONST_H +#define APCLIENT_CONST_H #include -#include "core/checks.h" -#include "core/items.h" +#include "checks.h" +#include "items.h" #include diff --git a/src/core/EchoSocket.cpp b/src/core/EchoSocket.cpp deleted file mode 100644 index c587fe8..0000000 --- a/src/core/EchoSocket.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include "core/EchoSocket.h" - -#include - -K_DYNAMIC_SINGLETON_IMPL(AP::EchoSocket); - -namespace AP { - -EchoSocket::EchoSocket() { - bool success; - - mpSocket = new kiwi::SyncSocket( // - SO_PF_INET, /* ipv4 */ - SO_SOCK_DGRAM /* udp = datagram*/ - ); - - ASSERT_PTR(mpSocket); - mpSocket->SetBlocking(false); - - // Packet data buffer - mpDataBuffer = new (kiwi::EMemory_MEM2) u8[MAX_PACKET_SIZE]; - ASSERT_PTR(mpDataBuffer); - - // Bind to any available local address - kiwi::SockAddr4 addr(kiwi::port::AP_COMM); - success = mpSocket->Bind(addr); - ASSERT_EX(success, "Can't bind socket"); - - // Host address now has the correct IP - u16 port = addr.port; - mpSocket->GetHostAddr(addr); - addr.port = port; - - kiwi::cout << "Echo socket listening on: " << kiwi::ToString(addr) - << kiwi::endl; - - for (;;) { - // Receive packet from the peer - kiwi::Optional nrecv = - mpSocket->RecvBytesFrom(mpDataBuffer, MAX_PACKET_SIZE, mPeerAddr); - - if (!nrecv) { - ASSERT_EX(false, "Socket error (errcode %d)", - kiwi::LibSO::GetLastError()); - } - - if (*nrecv > 0) { - kiwi::cout << "Received data from " << kiwi::ToString(mPeerAddr) - << "(" << *nrecv << " bytes)" << kiwi::endl; - - kiwi::IosObject acceptanceByte = 1; - - mpSocket->SendTo(acceptanceByte.Ref(), mPeerAddr); - } - } -} - -} // namespace AP \ No newline at end of file diff --git a/src/core/EchoSocket.h b/src/core/EchoSocket.h deleted file mode 100644 index d4124f8..0000000 --- a/src/core/EchoSocket.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef APCLIENT_CORE_ECHO_SOCKET_H -#define APCLIENT_CORE_ECHO_SOCKET_H -#include - -#include - -namespace AP { - -class EchoSocket : public kiwi::DynamicSingleton { - friend class kiwi::DynamicSingleton; - -private: - static const u32 MAX_PACKET_SIZE = 256; - -private: - static void SocketCallbackFunc(SOResult result, void* pArg); - - EchoSocket(); - -private: - kiwi::SyncSocket* mpSocket; - u8* mpDataBuffer; - kiwi::SockAddr4 mPeerAddr; -}; - -} // namespace AP - -#endif diff --git a/src/core/items.h b/src/items.h similarity index 95% rename from src/core/items.h rename to src/items.h index a2dd1ab..f63dd51 100644 --- a/src/core/items.h +++ b/src/items.h @@ -1,5 +1,5 @@ -#ifndef APCLIENT_CORE_ITEMS_H -#define APCLIENT_CORE_ITEMS_H +#ifndef APCLIENT_ITEMS_H +#define APCLIENT_ITEMS_H #include // clang-format off @@ -90,12 +90,12 @@ X(0x0700, ARCHERY_AIM_CIRCLE, "Archery - Aiming Circle") \ X(0x0701, ARCHERY_ARROW, "Progressive Arrow (Archery)") \ X(0x0702, ARCHERY_FRUIT_PROG, "Progressive Fruit (Archery)") \ - X(0x0702, ARCHERY_FRUIT_BEGINNER, "Archery Fruit Beginner") \ - X(0x0703, ARCHERY_FRUIT_INTERMEDIATE, "Archery Fruit Intermediate") \ - X(0x0704, ARCHERY_FRUIT_EXPERT, "Archery Fruit Expert") \ - X(0x0705, ARCHERY_BEGINNER, "Unlock Archery - Beginner") \ - X(0x0706, ARCHERY_INTERMEDIATE, "Unlock Archery - Intermediate") \ - X(0x0707, ARCHERY_EXPERT, "Unlock Archery - Expert") \ + X(0x0703, ARCHERY_FRUIT_BEGINNER, "Archery Fruit Beginner") \ + X(0x0704, ARCHERY_FRUIT_INTERMEDIATE, "Archery Fruit Intermediate") \ + X(0x0705, ARCHERY_FRUIT_EXPERT, "Archery Fruit Expert") \ + X(0x0706, ARCHERY_BEGINNER, "Unlock Archery - Beginner") \ + X(0x0707, ARCHERY_INTERMEDIATE, "Unlock Archery - Intermediate") \ + X(0x0708, ARCHERY_EXPERT, "Unlock Archery - Expert") \ X(0x0800, BASKETBALL_3PT_TIMER, "Basketball (3-Point Contest) Timer") \ X(0x0801, BASKETBALL_BONUS_BALLS, "Basketball (3-Point Contest) - Golden Balls") \ X(0x0900, BASKETBALL_PICKUP_TIMER, "Basketball (Pickup) Timer") \ @@ -162,8 +162,8 @@ X(0x1106, CYCLING_STAGE_5, "Unlock Cycling - Into Maka Wuhu") \ X(0x1107, CYCLING_STAGE_6, "Unlock Cycling - 3-Stage Race A") \ X(0x1108, CYCLING_STAGE_7, "Unlock Cycling - 3-Stage Race B") \ - X(0x1108, CYCLING_STAGE_8, "Unlock Cycling - 6 Stage") \ - X(0x1109, CYCLING_DRAFT, "Cycling - Drafting") \ + X(0x1109, CYCLING_STAGE_8, "Unlock Cycling - 6 Stage") \ + X(0x1110, CYCLING_DRAFT, "Cycling - Drafting") \ X(0x1200, SKYDIVING_MII, "Skydiving - Mii") \ X(0x1300, ISLAND_FLYOVER_TIMER, "Island Flyover Timer") \ X(0x1301, ISLAND_FLYOVER_DAY, "Unlock Island Flyover - Daytime") \ diff --git a/src/main.cpp b/src/main.cpp index ee6ef1a..4b59b64 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,5 @@ -#include "core/CheckMgr.h" -#include "core/CosmeticMgr.h" -#include "core/EchoSocket.h" -#include "core/ItemMgr.h" -#include "core/const.h" +#include "Cmn/System.h" +#include "const.h" #include #include @@ -25,16 +22,7 @@ void KokeshiMain() { kiwi::LibSO::Initialize(); // Archipelago initialization - AP::ItemMgr::CreateInstance(); - AP::CosmeticMgr::CreateInstance(); - AP::CheckMgr::CreateInstance(); - - // TODO: Move to debug menu eventually -#ifndef NDEBUG - AP::ItemMgr::GetInstance().Debug(); - AP::CosmeticMgr::GetInstance().Debug(); - AP::CheckMgr::GetInstance().Debug(); -#endif + AP::Cmn::System::Initialize(); // Register debug menu kiwi::SceneCreator::GetInstance().RegistDebugRoot( @@ -43,8 +31,6 @@ void KokeshiMain() { // Enter first scene kiwi::SceneCreator::GetInstance().ChangeBootScene(); - AP::EchoSocket::CreateInstance(); - // Enter game loop RP_GET_INSTANCE(RPSysSystem)->mainLoop(); diff --git a/src/packets.h b/src/packets.h new file mode 100644 index 0000000..d6c3e90 --- /dev/null +++ b/src/packets.h @@ -0,0 +1,43 @@ +#ifndef APCLIENT_PACKETS_H +#define APCLIENT_PACKETS_H +#include + +// Packet types are packed structures +#pragma pack(push, 1) + +namespace AP { + +/** + * @brief Common packet structure + */ +struct CommonPacket { + /* 0x00 */ u32 kind; //!< Type of this packet +}; + +/** + * @brief Connection packet (ConnectMsg) + */ +struct ConnectPacket : CommonPacket { + /* 0x01 */ union { + u32 raw; + u8 octets[4]; + } ip; //!< PC client IP address + + /* 0x05 */ u16 port; //!< PC client port +}; + +/** + * @brief Disconnection packet (DisconnectMsg) + */ +struct DisconnectPacket : CommonPacket {}; + +/** + * @brief Item packet (ItemMsg) + */ +struct ItemPacket : CommonPacket {}; + +} // namespace AP + +#pragma pack(pop) + +#endif diff --git a/src/hooks/trampoline.h b/src/trampoline.h similarity index 91% rename from src/hooks/trampoline.h rename to src/trampoline.h index 23a53d5..fb115b5 100644 --- a/src/hooks/trampoline.h +++ b/src/trampoline.h @@ -1,5 +1,5 @@ -#ifndef APCLIENT_HOOKS_TRAMPOLINE_H -#define APCLIENT_HOOKS_TRAMPOLINE_H +#ifndef APCLIENT_TRAMPOLINE_H +#define APCLIENT_TRAMPOLINE_H #include /** @@ -92,7 +92,7 @@ mflr r12 ; \ stw r12, (0x08 + length)(r1) ; \ mfcr r12 ; \ - stw r12, (0x88 + length)(r1) ; \ + stw r12, (0x88 + length)(r1) ; \ // clang-format on /** @@ -105,7 +105,7 @@ lwz r12, (0x08 + length)(r1); \ mtlr r12 ; \ lmw r3, (0x0C + length)(r1); \ - addi r1, r1, (0x100 + length); \ -// clang-format on + addi r1, r1, (0x100 + length); \ + // clang-format on #endif \ No newline at end of file