CIOWinManager implementation

This commit is contained in:
Jack Andersen 2015-08-25 15:34:56 -10:00
parent 3f1025abb3
commit a9cfd21ebc
12 changed files with 415 additions and 75 deletions

View File

@ -10,7 +10,7 @@ class CAudioStateWin : public CIOWin
{
public:
CAudioStateWin() : CIOWin("CAudioStateWin") {}
virtual bool OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue)
virtual CIOWin::EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue)
{
}
};

View File

@ -1,9 +1,9 @@
#ifndef __RETRO_CARCHITECTUREMESSAGE_HPP__
#define __RETRO_CARCHITECTUREMESSAGE_HPP__
#include <memory>
#include "GCNTypes.hpp"
#include "Input/CFinalInput.hpp"
#include "rstl.hpp"
namespace Retro
{
@ -11,14 +11,15 @@ class CIOWin;
enum EArchMsgTarget
{
TargetMainFlow = 0
TargetIOWinManager = 0
};
enum EArchMsgType
{
MsgDeleteIOWin = 0,
MsgRemoveIOWin = 0,
MsgCreateIOWin = 1,
MsgChangeIOWinPriority = 2,
MsgRemoveAllIOWins = 3,
MsgTimerTick = 4,
MsgUserInput = 5,
MsgSetGameState = 6,
@ -35,17 +36,24 @@ struct IArchMsgParm
struct CArchMsgParmInt32 : IArchMsgParm
{
u32 m_parm;
CArchMsgParmInt32(u32 parm) : m_parm(parm) {}
u32 x4_parm;
CArchMsgParmInt32(u32 parm) : x4_parm(parm) {}
};
struct CArchMsgParmVoidPtr : IArchMsgParm
{
void* x4_parm1;
CArchMsgParmVoidPtr(void* parm1)
: x4_parm1(parm1) {}
};
struct CArchMsgParmInt32Int32VoidPtr : IArchMsgParm
{
u32 m_parm1;
u32 m_parm2;
const void* m_parm3;
CArchMsgParmInt32Int32VoidPtr(u32 parm1, u32 parm2, const void* parm3)
: m_parm1(parm1), m_parm2(parm2), m_parm3(parm3) {}
u32 x4_parm1;
u32 x8_parm2;
void* xc_parm3;
CArchMsgParmInt32Int32VoidPtr(u32 parm1, u32 parm2, void* parm3)
: x4_parm1(parm1), x8_parm2(parm2), xc_parm3(parm3) {}
};
struct CArchMsgParmNull : IArchMsgParm
@ -54,37 +62,37 @@ struct CArchMsgParmNull : IArchMsgParm
struct CArchMsgParmReal32 : IArchMsgParm
{
float m_parm;
CArchMsgParmReal32(float parm) : m_parm(parm) {}
float x4_parm;
CArchMsgParmReal32(float parm) : x4_parm(parm) {}
};
struct CArchMsgParmUserInput : IArchMsgParm
{
CFinalInput m_parm;
CArchMsgParmUserInput(const CFinalInput& parm) : m_parm(parm) {}
CFinalInput x4_parm;
CArchMsgParmUserInput(const CFinalInput& parm) : x4_parm(parm) {}
};
struct CArchMsgParmControllerStatus : IArchMsgParm
{
u16 m_parm1;
bool m_parm2;
u16 x4_parm1;
bool x6_parm2;
CArchMsgParmControllerStatus(u16 a, bool b)
: m_parm1(a), m_parm2(b) {}
: x4_parm1(a), x6_parm2(b) {}
};
class CArchitectureMessage
{
EArchMsgTarget m_target;
EArchMsgType m_type;
std::unique_ptr<IArchMsgParm> m_parm;
EArchMsgTarget x0_target;
EArchMsgType x4_type;
rstl::rc_ptr<IArchMsgParm> x8_parm;
public:
CArchitectureMessage(EArchMsgTarget target, EArchMsgType type, IArchMsgParm* parm)
: m_target(target), m_type(type), m_parm(parm) {}
: x0_target(target), x4_type(type), x8_parm(parm) {}
EArchMsgTarget GetTarget() const {return m_target;}
EArchMsgType GetType() const {return m_type;}
EArchMsgTarget GetTarget() const {return x0_target;}
EArchMsgType GetType() const {return x4_type;}
template <class T>
const T* GetParm() const {return dynamic_cast<T*>(m_parm.get());}
const T* GetParm() const {return dynamic_cast<T*>(x8_parm.get());}
};
class MakeMsg
@ -126,13 +134,13 @@ public:
{
return *msg.GetParm<CArchMsgParmInt32Int32VoidPtr>();
}
static CArchitectureMessage CreateCreateIOWin(EArchMsgTarget target, int pmin, int pmax, const CIOWin* iowin)
static CArchitectureMessage CreateCreateIOWin(EArchMsgTarget target, int pmin, int pmax, CIOWin* iowin)
{
return CArchitectureMessage(target, MsgCreateIOWin, new CArchMsgParmInt32Int32VoidPtr(pmin, pmax, iowin));
}
static const CArchMsgParmInt32Int32VoidPtr& GetParmDeleteIOWin(const CArchitectureMessage& msg)
static const CArchMsgParmVoidPtr& GetParmDeleteIOWin(const CArchitectureMessage& msg)
{
return *msg.GetParm<CArchMsgParmInt32Int32VoidPtr>();
return *msg.GetParm<CArchMsgParmVoidPtr>();
}
};

View File

@ -11,18 +11,18 @@ class CArchitectureQueue
{
std::list<CArchitectureMessage> m_list;
public:
void PushMessage(CArchitectureMessage&& msg)
void Push(CArchitectureMessage&& msg)
{
m_list.push_back(std::move(msg));
}
const CArchitectureMessage& PeekMessage() const
{
return m_list.front();
}
void PopMessage()
CArchitectureMessage Pop()
{
CArchitectureMessage msg = std::move(m_list.front());
m_list.pop_front();
return msg;
}
void Clear() {m_list.clear();}
operator bool() {return m_list.size() != 0;}
};
}

View File

@ -2,6 +2,7 @@
#define __RETRO_CIOWIN_HPP__
#include <string>
#include "rstl.hpp"
namespace Retro
{
@ -10,16 +11,31 @@ class CArchitectureQueue;
class CIOWin
{
const char* m_name;
std::string m_name;
size_t m_nameHash;
public:
enum EMessageReturn
{
MsgRetNormal = 0,
MsgRetExit = 1,
MsgRetRemoveIOWinAndExit = 2,
MsgRetRemoveIOWin = 3
};
virtual ~CIOWin() {}
CIOWin(const char* name) : m_name(name) {}
virtual bool OnMessage(const CArchitectureMessage&, CArchitectureQueue&)=0;
CIOWin(const std::string& name) : m_name(name) {m_nameHash = std::hash<std::string>()(name);}
virtual EMessageReturn OnMessage(const CArchitectureMessage&, CArchitectureQueue&)=0;
virtual bool GetIsContinueDraw() const {return true;}
virtual void Draw() const {}
virtual void PreDraw() const {}
const std::string& GetName() const {return m_name;}
size_t GetNameHash() const {return m_nameHash;}
};
static bool operator==(rstl::rc_ptr<CIOWin> a, rstl::rc_ptr<CIOWin> b)
{
return a.get() == b.get();
}
}
#endif // __RETRO_CIOWIN_HPP__

View File

@ -8,14 +8,276 @@ bool CIOWinManager::OnIOWinMessage(const CArchitectureMessage& msg)
{
switch (msg.GetType())
{
case MsgRemoveIOWin:
{
const CArchMsgParmVoidPtr& parm = MakeMsg::GetParmDeleteIOWin(msg);
rstl::rc_ptr<CIOWin> iow = FindIOWin(*static_cast<const std::string*>(parm.x4_parm1));
if (iow)
RemoveIOWin(iow);
return false;
}
case MsgCreateIOWin:
{
const CArchMsgParmInt32Int32VoidPtr& parm = MakeMsg::GetParmCreateIOWin(msg);
rstl::rc_ptr<CIOWin> iow(static_cast<CIOWin*>(parm.xc_parm3));
AddIOWin(iow, parm.x4_parm1, parm.x8_parm2);
return false;
}
case MsgChangeIOWinPriority:
{
const CArchMsgParmInt32Int32VoidPtr& parm = MakeMsg::GetParmChangeIOWinPriority(msg);
rstl::rc_ptr<CIOWin> iow = FindIOWin(*static_cast<const std::string*>(parm.xc_parm3));
if (iow)
ChangeIOWinPriority(iow, parm.x4_parm1, parm.x8_parm2);
return false;
}
case MsgRemoveAllIOWins:
{
RemoveAllIOWins();
return true;
}
default: break;
}
return false;
}
void CIOWinManager::Draw() const
{
IOWinPQNode* node = x0_rootDraw;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
iow->PreDraw();
if (!iow->GetIsContinueDraw())
break;
node = node->x8_next;
}
node = x0_rootDraw;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
iow->Draw();
if (!iow->GetIsContinueDraw())
break;
node = node->x8_next;
}
}
bool CIOWinManager::DistributeOneMessage(const CArchitectureMessage& msg,
CArchitectureQueue& queue)
{
CIOWinManager::IOWinPQNode* node = x4_rootPump;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
CIOWin::EMessageReturn mret = iow->OnMessage(msg, x8_internalQueue);
while (x8_internalQueue)
{
CArchitectureMessage msg = x8_internalQueue.Pop();
if (msg.GetTarget() == TargetIOWinManager)
{
if (OnIOWinMessage(msg))
{
x8_internalQueue.Clear();
queue.Clear();
return true;
}
}
else
queue.Push(std::move(msg));
}
switch (mret)
{
case CIOWin::MsgRetRemoveIOWinAndExit:
case CIOWin::MsgRetRemoveIOWin:
RemoveIOWin(iow);
default: break;
}
switch (mret)
{
case CIOWin::MsgRetExit:
case CIOWin::MsgRetRemoveIOWinAndExit:
return false;
default: break;
}
node = node->x8_next;
}
return false;
}
void CIOWinManager::PumpMessages(CArchitectureQueue& queue)
{
while (queue)
{
CArchitectureMessage msg = queue.Pop();
if (DistributeOneMessage(msg, queue))
break;
}
}
rstl::rc_ptr<CIOWin> CIOWinManager::FindIOWin(const std::string& name)
{
size_t findHash = std::hash<std::string>()(name);
CIOWinManager::IOWinPQNode* node = x4_rootPump;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
if (iow->GetNameHash() == findHash)
return iow;
node = node->x8_next;
}
node = x0_rootDraw;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
if (iow->GetNameHash() == findHash)
return iow;
node = node->x8_next;
}
return rstl::rc_ptr<CIOWin>();
}
void CIOWinManager::ChangeIOWinPriority(rstl::ncrc_ptr<CIOWin> chIow, int pumpPrio, int drawPrio)
{
CIOWinManager::IOWinPQNode* node = x4_rootPump;
CIOWinManager::IOWinPQNode* prevNode = nullptr;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
if (iow == chIow)
{
if (prevNode)
prevNode->x8_next = node->x8_next;
node->x4_prio = pumpPrio;
CIOWinManager::IOWinPQNode* testNode = x4_rootPump;
CIOWinManager::IOWinPQNode* testPrevNode = nullptr;
while (testNode->x4_prio > pumpPrio)
{
testPrevNode = testNode;
testNode = testNode->x8_next;
}
node->x8_next = testNode;
if (testPrevNode)
testPrevNode->x8_next = node;
else
x4_rootPump = node;
break;
}
prevNode = node;
node = node->x8_next;
}
node = x0_rootDraw;
prevNode = nullptr;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
if (iow == chIow)
{
if (prevNode)
prevNode->x8_next = node->x8_next;
node->x4_prio = drawPrio;
CIOWinManager::IOWinPQNode* testNode = x0_rootDraw;
CIOWinManager::IOWinPQNode* testPrevNode = nullptr;
while (testNode->x4_prio > drawPrio)
{
testPrevNode = testNode;
testNode = testNode->x8_next;
}
node->x8_next = testNode;
if (testPrevNode)
testPrevNode->x8_next = node;
else
x0_rootDraw = node;
break;
}
prevNode = node;
node = node->x8_next;
}
}
void CIOWinManager::RemoveAllIOWins()
{
while (x0_rootDraw)
RemoveIOWin(x0_rootDraw->GetIOWin());
while (x4_rootPump)
RemoveIOWin(x4_rootPump->GetIOWin());
}
void CIOWinManager::RemoveIOWin(rstl::ncrc_ptr<CIOWin> chIow)
{
CIOWinManager::IOWinPQNode* node = x4_rootPump;
CIOWinManager::IOWinPQNode* prevNode = nullptr;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
if (iow == chIow)
{
if (prevNode)
prevNode->x8_next = node->x8_next;
else
x4_rootPump = node->x8_next;
delete node;
break;
}
prevNode = node;
node = node->x8_next;
}
node = x0_rootDraw;
prevNode = nullptr;
while (node)
{
rstl::rc_ptr<CIOWin> iow = node->GetIOWin();
if (iow == chIow)
{
if (prevNode)
prevNode->x8_next = node->x8_next;
else
x0_rootDraw = node->x8_next;
delete node;
break;
}
prevNode = node;
node = node->x8_next;
}
}
void CIOWinManager::AddIOWin(rstl::ncrc_ptr<CIOWin> chIow, int pumpPrio, int drawPrio)
{
CIOWinManager::IOWinPQNode* node = x4_rootPump;
CIOWinManager::IOWinPQNode* prevNode = nullptr;
while (node && pumpPrio > node->x4_prio)
{
prevNode = node;
node = node->x8_next;
}
CIOWinManager::IOWinPQNode* newNode = new CIOWinManager::IOWinPQNode(chIow, pumpPrio, node);
if (prevNode)
prevNode->x8_next = newNode;
else
x4_rootPump = newNode;
node = x0_rootDraw;
prevNode = nullptr;
while (node && drawPrio > node->x4_prio)
{
prevNode = node;
node = node->x8_next;
}
newNode = new CIOWinManager::IOWinPQNode(chIow, drawPrio, node);
if (prevNode)
prevNode->x8_next = newNode;
else
x0_rootDraw = newNode;
}
}

View File

@ -2,7 +2,10 @@
#define __RETRO_CIOWINMANAGER_HPP__
#include <memory>
#include <list>
#include "CIOWin.hpp"
#include "rstl.hpp"
#include "CArchitectureQueue.hpp"
namespace Retro
{
@ -11,17 +14,31 @@ class CIOWinManager
{
struct IOWinPQNode
{
std::shared_ptr<CIOWin> m_iowin;
int m_prio;
CIOWinManager::IOWinPQNode* m_prev;
IOWinPQNode(std::weak_ptr<CIOWin> iowin, int prio,
CIOWinManager::IOWinPQNode* prev)
: m_iowin(iowin), m_prio(prio), m_prev(prev) {}
std::shared_ptr<CIOWin> GetIOWin() const {return m_iowin;}
rstl::rc_ptr<CIOWin> x0_iowin;
int x4_prio;
CIOWinManager::IOWinPQNode* x8_next;
IOWinPQNode(rstl::ncrc_ptr<CIOWin> iowin, int prio,
CIOWinManager::IOWinPQNode* next)
: x0_iowin(iowin), x4_prio(prio), x8_next(next) {}
rstl::rc_ptr<CIOWin> GetIOWin() const {return rstl::rc_ptr<CIOWin>(x0_iowin);}
};
IOWinPQNode* x0_rootDraw = nullptr;
IOWinPQNode* x4_rootPump = nullptr;
CArchitectureQueue x8_internalQueue;
public:
bool OnIOWinMessage(const CArchitectureMessage& msg);
void Draw() const;
bool DistributeOneMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue);
void PumpMessages(CArchitectureQueue& queue);
rstl::rc_ptr<CIOWin> FindIOWin(const std::string& name);
void ChangeIOWinPriority(rstl::ncrc_ptr<CIOWin>, int pumpPrio, int drawPrio);
void RemoveAllIOWins();
void RemoveIOWin(rstl::ncrc_ptr<CIOWin>);
void AddIOWin(rstl::ncrc_ptr<CIOWin>, int pumpPrio, int drawPrio);
};
}
#endif // __RETRO_CIOWINMANAGER_HPP__

View File

@ -6,7 +6,7 @@
namespace Retro
{
bool CMFGameLoader::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue)
CIOWin::EMessageReturn CMFGameLoader::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue)
{
switch (msg.GetType())
{
@ -17,7 +17,7 @@ bool CMFGameLoader::OnMessage(const CArchitectureMessage& msg, CArchitectureQueu
}
default: break;
}
return true;
return MsgRetExit;
}
void CMFGameLoader::Draw() const

View File

@ -10,7 +10,7 @@ class CMFGameLoader : public CIOWin
{
public:
CMFGameLoader() : CIOWin("CMFGameLoader") {}
bool OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue);
EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue);
void Draw() const;
};

View File

@ -13,12 +13,12 @@ void CMainFlow::SetGameState(EClientFlowStates state, CArchitectureQueue& queue)
switch (state)
{
case StateGameLoad:
queue.PushMessage(std::move(MakeMsg::CreateCreateIOWin(TargetMainFlow, 10, 1000, new CMFGameLoader())));
queue.Push(std::move(MakeMsg::CreateCreateIOWin(TargetIOWinManager, 10, 1000, new CMFGameLoader())));
break;
default: break;
}
}
bool CMainFlow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue)
CIOWin::EMessageReturn CMainFlow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue)
{
switch (msg.GetType())
{
@ -28,12 +28,12 @@ bool CMainFlow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& q
case MsgSetGameState:
{
CArchMsgParmInt32 state = MakeMsg::GetParmNewGameflowState(msg);
SetGameState(EClientFlowStates(state.m_parm), queue);
return true;
SetGameState(EClientFlowStates(state.x4_parm), queue);
return MsgRetExit;
}
default: break;
}
return false;
return MsgRetNormal;
}
}

View File

@ -19,7 +19,7 @@ public:
CMainFlow() : CIOWin("CMainFlow") {}
void AdvanceGameState(CArchitectureQueue& queue);
void SetGameState(EClientFlowStates state, CArchitectureQueue& queue);
bool OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue);
EMessageReturn OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue);
bool GetIsContinueDraw() const {return false;}
void Draw() const {}
};

View File

@ -15,21 +15,15 @@ public:
class CVParamTransfer
{
rstl::CRefData* m_refData;
rstl::rc_ptr<IVParamObj> m_ref;
public:
CVParamTransfer(rstl::CRefData* rd) : m_refData(rd) {m_refData->AddRef();}
~CVParamTransfer()
{
if (m_refData->DelRef() <= 0)
{
delete static_cast<IVParamObj*>(m_refData->GetPtr());
delete m_refData;
}
}
IVParamObj* GetObj() const {return static_cast<IVParamObj*>(m_refData->GetPtr());}
CVParamTransfer ShareTransferRef() {return CVParamTransfer(m_refData);}
CVParamTransfer();
CVParamTransfer(IVParamObj* obj) : m_ref(obj) {}
CVParamTransfer(const CVParamTransfer& other) : m_ref(other.m_ref) {}
IVParamObj* GetObj() const {return m_ref.get();}
CVParamTransfer ShareTransferRef() {return CVParamTransfer(*this);}
static CVParamTransfer Null() {return CVParamTransfer(&rstl::CRefData::sNull);}
static CVParamTransfer Null() {return CVParamTransfer();}
};
template<class T>
@ -40,7 +34,6 @@ protected:
~TObjOwnerParam() {}
public:
TObjOwnerParam(T&& obj) : m_param(std::move(obj)) {}
CVParamTransfer NewTransferRef() {return CVParamTransfer(new rstl::CRefData(this));}
};
}

View File

@ -22,19 +22,63 @@ public:
*/
class CRefData
{
void* m_ptr;
int m_refCount;
void* x0_ptr;
int x4_refCount;
public:
CRefData() : m_ptr(nullptr), m_refCount(0xffffff) {}
CRefData(void* ptr) : m_ptr(ptr), m_refCount(0) {}
CRefData() : x0_ptr(nullptr), x4_refCount(0xffffff) {}
CRefData(void* ptr) : x0_ptr(ptr), x4_refCount(0) {}
void* GetPtr() const {return m_ptr;}
int AddRef() {return ++m_refCount;}
int DelRef() {return --m_refCount;}
void* GetPtr() const {return x0_ptr;}
int AddRef() {return ++x4_refCount;}
int DelRef() {return --x4_refCount;}
static CRefData sNull;
};
template<class T>
class ncrc_ptr;
/**
* @brief Reference-counted shared smart pointer
*/
template<class T>
class rc_ptr
{
CRefData* m_aux;
friend class ncrc_ptr<T>;
public:
rc_ptr() : m_aux(&CRefData::sNull) {m_aux->AddRef();}
rc_ptr(void* ptr) : m_aux(new CRefData(ptr)) {m_aux->AddRef();}
rc_ptr(const rc_ptr<T>& other) : m_aux(other.m_aux) {m_aux->AddRef();}
rc_ptr(rc_ptr<T>&& other) : m_aux(other.m_aux) {other.m_aux = nullptr;}
rc_ptr(const ncrc_ptr<T>& other) : m_aux(other.m_aux) {m_aux->AddRef();}
~rc_ptr()
{
if (m_aux && !m_aux->DelRef())
{
delete static_cast<T*>(m_aux->GetPtr());
delete m_aux;
}
}
T* operator->() const {return static_cast<T*>(m_aux->GetPtr());}
T& operator*() const {return *static_cast<T*>(m_aux->GetPtr());}
T* get() const {return static_cast<T*>(m_aux->GetPtr());}
operator bool() {return m_aux->GetPtr() != nullptr;}
};
/**
* @brief Non-reference-counted shared smart pointer
*/
template<class T>
class ncrc_ptr
{
CRefData* m_aux;
friend class rc_ptr<T>;
public:
ncrc_ptr(const rc_ptr<T>& other) : m_aux(other.m_aux) {}
};
}
#endif // __RSTL_HPP__