MxNotificationManager and MxParam initial work. (#78)

* MxNotificationManager initial work.

* Add .swp files to .gitignore.

* Checkpoint before anything too crazy with param

* Cleanup and add MxParam.

* Checkpoint for everything except MxNotificationManager::Register.

* Add int return type to MxCore::GetId instead of relying on implicit function nonsense.

* Add stlcompat.h so this can still be built on modern compilers, fix affected type size asserts.

* Switch to Mx types

* Add BUILD_COMPAT option to CMake so the project can still be built with modern compilers.

* Change vtable14 and vtable18 to Register and Unregister in MxTickleManager.

* Remove last unsigned int reference to id type.

* Remove MxList, use one inherited class per type. Improves accuracy again.

* Address compiler compatibility code review.

* Match MxNotificationManager::Register.

* Re-enable MxNotificationManager DECOMP_SIZE_ASSERT.
This commit is contained in:
pewpew
2023-07-16 01:43:08 -05:00
committed by GitHub
parent 2ffe227d82
commit 4a50a9ff56
9 changed files with 250 additions and 12 deletions

1
.gitignore vendored
View File

@@ -4,3 +4,4 @@ Release/
ISLE.EXE ISLE.EXE
LEGO1.DLL LEGO1.DLL
build/ build/
*.swp

View File

@@ -135,6 +135,7 @@ add_library(lego1 SHARED
LEGO1/mxomnicreateparam.cpp LEGO1/mxomnicreateparam.cpp
LEGO1/mxomnicreateparambase.cpp LEGO1/mxomnicreateparambase.cpp
LEGO1/mxpalette.cpp LEGO1/mxpalette.cpp
LEGO1/mxparam.cpp
LEGO1/mxpresenter.cpp LEGO1/mxpresenter.cpp
LEGO1/mxscheduler.cpp LEGO1/mxscheduler.cpp
LEGO1/mxsemaphore.cpp LEGO1/mxsemaphore.cpp

View File

@@ -11,6 +11,19 @@
#define COMPAT_CONST #define COMPAT_CONST
#endif #endif
#define MSVC420_VERSION 1020
// STL compatibility.
#if defined(_MSC_VER) && _MSC_VER <= MSVC420_VERSION
#include <STL.H>
#else
#include <algorithm>
#include <list>
using namespace std;
template <class T>
using List = list<T>;
#endif
// We use `override` so newer compilers can tell us our vtables are valid, // We use `override` so newer compilers can tell us our vtables are valid,
// however this keyword was added in C++11, so we define it as empty for // however this keyword was added in C++11, so we define it as empty for
// compatibility with older compilers. // compatibility with older compilers.

View File

@@ -31,8 +31,13 @@ public:
return !strcmp(name, MxCore::ClassName()); return !strcmp(name, MxCore::ClassName());
} }
inline MxU32 GetId()
{
return m_id;
}
private: private:
unsigned int m_id; MxU32 m_id;
}; };

View File

@@ -1,15 +1,143 @@
#include "legoomni.h"
#include "mxautolocker.h"
#include "mxcore.h"
#include "mxnotificationmanager.h" #include "mxnotificationmanager.h"
#include "mxparam.h"
#include "mxtypes.h"
// OFFSET: LEGO1 0x100ac450 STUB #include "compat.h"
#include "decomp.h"
DECOMP_SIZE_ASSERT(MxNotification, 0x8);
DECOMP_SIZE_ASSERT(MxNotificationManager, 0x40);
// OFFSET: LEGO1 0x100ac220
MxNotification::MxNotification(MxCore *p_target, MxParam *p_param)
{
m_target = p_target;
m_param = p_param->Clone();
}
// OFFSET: LEGO1 0x100ac240
MxNotification::~MxNotification()
{
delete m_param;
}
// OFFSET: LEGO1 0x100ac250
MxNotificationManager::MxNotificationManager() : MxCore(), m_lock(), m_listenerIds()
{
m_unk2c = 0;
m_queue = NULL;
m_active = TRUE;
m_sendList = NULL;
}
// OFFSET: LEGO1 0x100ac450
MxNotificationManager::~MxNotificationManager() MxNotificationManager::~MxNotificationManager()
{
MxAutoLocker lock(&m_lock);
Tickle();
delete m_queue;
m_queue = NULL;
TickleManager()->Unregister(this);
}
// OFFSET: LEGO1 0x100ac800
MxResult MxNotificationManager::Tickle()
{
m_sendList = new MxNotificationPtrList();
if (m_sendList == NULL) {
return FAILURE;
}
else {
{
MxAutoLocker lock(&m_lock);
swap(m_queue, m_sendList);
}
while (m_sendList->size() != 0) {
MxNotification *notif = m_sendList->front();
m_sendList->pop_front();
notif->GetTarget()->Notify(*notif->GetParam());
delete notif;
}
delete m_sendList;
m_sendList = NULL;
return SUCCESS;
}
}
// OFFSET: LEGO1 0x100ac600
MxResult MxNotificationManager::Create(MxS32 p_unk1, MxS32 p_unk2)
{
MxResult result = SUCCESS;
m_queue = new MxNotificationPtrList();
if (m_queue == NULL) {
result = FAILURE;
}
else {
TickleManager()->Register(this, 10);
}
return result;
}
// OFFSET: LEGO1 0x100acd20
void MxNotificationManager::Register(MxCore *p_listener)
{
MxAutoLocker lock(&m_lock);
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
if (it != m_listenerIds.end())
return;
m_listenerIds.push_back(p_listener->GetId());
}
// OFFSET: LEGO1 0x100acdf0
void MxNotificationManager::Unregister(MxCore *p_listener)
{
MxAutoLocker lock(&m_lock);
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
if (it != m_listenerIds.end()) {
m_listenerIds.erase(it);
FlushPending(p_listener);
}
}
// OFFSET: LEGO1 0x100ac990 STUB
void MxNotificationManager::FlushPending(MxCore *p_listener)
{ {
// TODO // TODO
} }
// OFFSET: LEGO1 0x100ac800 STUB // OFFSET: LEGO1 0x100ac6c0
MxLong MxNotificationManager::Tickle() MxResult MxNotificationManager::Send(MxCore *p_listener, MxParam *p_param)
{ {
// TODO MxAutoLocker lock(&m_lock);
return 0; if (m_active == FALSE) {
} return FAILURE;
}
else {
MxIdList::iterator it = find(m_listenerIds.begin(), m_listenerIds.end(), p_listener->GetId());
if (it == m_listenerIds.end()) {
return FAILURE;
}
else {
MxNotification *notif = new MxNotification(p_listener, p_param);
if (notif != NULL) {
m_queue->push_back(notif);
return SUCCESS;
}
}
}
return FAILURE;
}

View File

@@ -2,16 +2,62 @@
#define MXNOTIFICATIONMANAGER_H #define MXNOTIFICATIONMANAGER_H
#include "mxcore.h" #include "mxcore.h"
#include "mxcriticalsection.h"
#include "mxtypes.h"
#include "compat.h"
class MxNotification
{
public:
MxNotification(MxCore *p_target, MxParam *p_param);
~MxNotification();
inline MxCore *GetTarget()
{
return m_target;
}
inline MxParam *GetParam()
{
return m_param;
}
private:
MxCore *m_target; // 0x0
MxParam *m_param; // 0x4
};
class MxIdList : public List<MxU32>
{};
class MxNotificationPtrList : public List<MxNotification *>
{};
// VTABLE 0x100dc078 // VTABLE 0x100dc078
class MxNotificationManager : public MxCore class MxNotificationManager : public MxCore
{ {
private:
MxNotificationPtrList *m_queue; // 0x8
MxNotificationPtrList *m_sendList; // 0xc
MxCriticalSection m_lock; // 0x10
MxS32 m_unk2c; // 0x2c
MxIdList m_listenerIds; // 0x30
MxBool m_active; // 0x3c
public: public:
virtual ~MxNotificationManager(); // vtable+0x0 MxNotificationManager();
virtual ~MxNotificationManager(); // vtable+0x0 (scalar deleting destructor)
virtual MxLong Tickle(); // vtable+0x8 virtual MxResult Tickle(); // vtable+0x8
// TODO: Where does this method come from?
virtual MxResult Create(MxS32 p_unk1, MxS32 p_unk2); // vtable+0x14
void Register(MxCore *p_listener);
void Unregister(MxCore *p_listener);
MxResult Send(MxCore *p_listener, MxParam *p_param);
// 0x10: MxCriticalSection private:
void FlushPending(MxCore *p_listener);
}; };
#endif // MXNOTIFICATIONMANAGER_H #endif // MXNOTIFICATIONMANAGER_H

11
LEGO1/mxparam.cpp Normal file
View File

@@ -0,0 +1,11 @@
#include "mxparam.h"
#include "decomp.h"
DECOMP_SIZE_ASSERT(MxParam, 0xc);
// OFFSET: LEGO1 0x10010390
MxParam* MxParam::Clone()
{
return new MxParam(m_type, m_sender);
}

33
LEGO1/mxparam.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef MXPARAM_H
#define MXPARAM_H
#include "mxomnicreateparambase.h"
#include "mxtypes.h"
class MxCore;
// VTABLE 0x100d56e0
class MxParam : public MxOmniCreateParamBase
{
public:
inline MxParam(MxS32 p_type, MxCore *p_sender) : MxOmniCreateParamBase(), m_type(p_type), m_sender(p_sender){}
virtual ~MxParam(){}; // vtable+0x0 (scalar deleting destructor)
virtual MxParam *Clone(); // vtable+0x4
inline MxS32 GetType() const
{
return m_type;
}
inline MxCore *GetSender() const
{
return m_sender;
}
private:
MxS32 m_type; // 0x4
MxCore *m_sender; // 0x8
};
#endif // MXPARAM_H

View File

@@ -12,8 +12,8 @@ public:
virtual MxLong Tickle(); virtual MxLong Tickle();
virtual const char *ClassName() const; virtual const char *ClassName() const;
virtual MxBool IsA(const char *name) const; virtual MxBool IsA(const char *name) const;
virtual void vtable14(); virtual void Register(MxCore *p_listener, int p_milliseconds);
virtual void vtable18(); virtual void Unregister(MxCore *p_listener);
virtual void vtable1c(void *v, int p); virtual void vtable1c(void *v, int p);
virtual void vtable20(); virtual void vtable20();
}; };