mirror of
https://github.com/isledecomp/isle-portable.git
synced 2024-11-15 03:24:59 -05:00
Implement MxAtomId and reference counter (stl set) (#109)
* Implement MxAtomId and reference counter (stl set) * Partial success in hiding 4786 warning spam. * Build out most of MxOmni::Destroy since it also touches the set * Add some size asserts
This commit is contained in:
parent
75c1276292
commit
bb0d5be921
8 changed files with 209 additions and 8 deletions
|
@ -92,6 +92,7 @@ add_library(lego1 SHARED
|
|||
LEGO1/legoworldpresenter.cpp
|
||||
LEGO1/motorcycle.cpp
|
||||
LEGO1/mxatomid.cpp
|
||||
LEGO1/mxatomidcounter.cpp
|
||||
LEGO1/mxaudiopresenter.cpp
|
||||
LEGO1/mxautolocker.cpp
|
||||
LEGO1/mxbackgroundaudiomanager.cpp
|
||||
|
|
|
@ -14,6 +14,11 @@
|
|||
// DIsable "nonstandard extension used : 'bool'" warning spam
|
||||
#pragma warning( disable : 4237 )
|
||||
|
||||
// Disable "identifier was truncated to '255' characters" warning.
|
||||
// Impossible to avoid this if using STL map or set.
|
||||
// This removes most (but not all) occurrences of the warning.
|
||||
#pragma warning( disable : 4786 )
|
||||
|
||||
#define MSVC420_VERSION 1020
|
||||
|
||||
// STL compatibility.
|
||||
|
@ -22,6 +27,7 @@
|
|||
#else
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <set>
|
||||
using namespace std;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,20 +1,97 @@
|
|||
#include "mxatomid.h"
|
||||
#include "mxomni.h"
|
||||
|
||||
// OFFSET: LEGO1 0x100acf90
|
||||
MxAtomId::MxAtomId(const char *, LookupMode)
|
||||
MxAtomId::MxAtomId(const char *p_str, LookupMode p_mode)
|
||||
{
|
||||
// TODO
|
||||
if (!MxOmni::GetInstance())
|
||||
return;
|
||||
|
||||
if (!AtomIdCounterSet())
|
||||
return;
|
||||
|
||||
MxAtomIdCounter *counter = GetCounter(p_str, p_mode);
|
||||
m_internal = counter->GetKey()->GetData();
|
||||
counter->Inc();
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100acfd0
|
||||
MxAtomId::~MxAtomId()
|
||||
{
|
||||
// TODO
|
||||
Destroy();
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100acfe0
|
||||
void MxAtomId::Destroy()
|
||||
{
|
||||
if (!m_internal)
|
||||
return;
|
||||
|
||||
if (!MxOmni::GetInstance())
|
||||
return;
|
||||
|
||||
if (!AtomIdCounterSet())
|
||||
return;
|
||||
|
||||
// The dtor is called on the counter object immediately,
|
||||
// so this syntax should be correct.
|
||||
MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find(
|
||||
&MxAtomIdCounter(m_internal)
|
||||
);
|
||||
|
||||
MxAtomIdCounter *counter = (MxAtomIdCounter*)(*it);
|
||||
counter->Dec();
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ad1c0
|
||||
MxAtomId &MxAtomId::operator=(const MxAtomId &id)
|
||||
MxAtomId &MxAtomId::operator=(const MxAtomId &p_atomId)
|
||||
{
|
||||
// TODO
|
||||
if (m_internal)
|
||||
Destroy();
|
||||
|
||||
if (p_atomId.m_internal && MxOmni::GetInstance() && AtomIdCounterSet()) {
|
||||
MxAtomIdCounter *counter = GetCounter(p_atomId.m_internal, LookupMode_Exact);
|
||||
counter->Inc();
|
||||
}
|
||||
|
||||
m_internal = p_atomId.m_internal;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ad210
|
||||
MxAtomIdCounter* MxAtomId::GetCounter(const char *p_str, LookupMode p_mode)
|
||||
{
|
||||
MxAtomId _unused;
|
||||
MxAtomIdCounter *counter = new MxAtomIdCounter(p_str);
|
||||
|
||||
switch (p_mode) {
|
||||
case LookupMode_LowerCase:
|
||||
case LookupMode_LowerCase2:
|
||||
counter->GetKey()->ToLowerCase();
|
||||
break;
|
||||
case LookupMode_UpperCase:
|
||||
counter->GetKey()->ToUpperCase();
|
||||
break;
|
||||
}
|
||||
|
||||
MxAtomIdCounterSet::iterator it = AtomIdCounterSet()->find(counter);
|
||||
if (it != AtomIdCounterSet()->end()) {
|
||||
// Counter already in the set. Delete temp value and return it.
|
||||
delete counter;
|
||||
counter = *it;
|
||||
} else {
|
||||
// Counter is not in the set. Add it.
|
||||
AtomIdCounterSet()->insert(counter);
|
||||
}
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ad7e0
|
||||
void MxAtomId::Clear()
|
||||
{
|
||||
// Reset but do not delete MxAtomId object.
|
||||
Destroy();
|
||||
m_internal = NULL;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define MXATOMID_H
|
||||
|
||||
#include "mxtypes.h"
|
||||
#include "mxatomidcounter.h"
|
||||
|
||||
enum LookupMode
|
||||
{
|
||||
|
@ -27,9 +28,13 @@ class MxAtomId
|
|||
{
|
||||
return this->m_internal == other.m_internal;
|
||||
}
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
char *m_internal;
|
||||
MxAtomIdCounter* GetCounter(const char *, LookupMode);
|
||||
void Destroy();
|
||||
|
||||
const char *m_internal;
|
||||
};
|
||||
|
||||
#endif // MXATOMID_H
|
||||
|
|
18
LEGO1/mxatomidcounter.cpp
Normal file
18
LEGO1/mxatomidcounter.cpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include "mxatomidcounter.h"
|
||||
#include "decomp.h"
|
||||
|
||||
DECOMP_SIZE_ASSERT(MxAtomIdCounter, 0x14);
|
||||
DECOMP_SIZE_ASSERT(MxAtomIdCounterSet, 0x10);
|
||||
|
||||
// OFFSET: LEGO1 0x100ad7f0
|
||||
void MxAtomIdCounter::Inc()
|
||||
{
|
||||
m_value++;
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100ad800
|
||||
void MxAtomIdCounter::Dec()
|
||||
{
|
||||
if (m_value)
|
||||
m_value--;
|
||||
}
|
49
LEGO1/mxatomidcounter.h
Normal file
49
LEGO1/mxatomidcounter.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef MXATOMIDCOUNTER_H
|
||||
#define MXATOMIDCOUNTER_H
|
||||
|
||||
#include "mxstring.h"
|
||||
#include "compat.h" // STL
|
||||
|
||||
// Counts the number of existing MxAtomId objects based
|
||||
// on the matching char* string. A <map> seems fit for purpose here:
|
||||
// We have an MxString as a key and MxU16 as the value.
|
||||
// And yet a <set> is the best match. The malloc in MxOmni::Create
|
||||
// for the _Nil node asks for more bytes than a regular node if a <map>
|
||||
// is used, but all nodes are 20 bytes wide with a <set>.
|
||||
// Also: the increment/decrement methods suggest a custom type was used
|
||||
// for the combined key_value_pair, which doesn't seem possible with <map>.
|
||||
|
||||
// SIZE: 0x14 (including padding)
|
||||
class MxAtomIdCounter
|
||||
{
|
||||
public:
|
||||
// always inlined
|
||||
MxAtomIdCounter(const char *p_str)
|
||||
{
|
||||
m_key = p_str;
|
||||
m_value = 0;
|
||||
}
|
||||
|
||||
void Inc();
|
||||
void Dec();
|
||||
inline MxString* GetKey() { return &m_key; };
|
||||
inline MxU16 GetValue() { return m_value; };
|
||||
|
||||
private:
|
||||
MxString m_key;
|
||||
MxU16 m_value;
|
||||
};
|
||||
|
||||
struct MxAtomIdCounterCompare
|
||||
{
|
||||
// OFFSET: LEGO1 0x100ad120
|
||||
int operator()(MxAtomIdCounter* const & p_val0, MxAtomIdCounter* const & p_val1) const
|
||||
{
|
||||
return strcmp(p_val0->GetKey()->GetData(), p_val1->GetKey()->GetData()) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
class MxAtomIdCounterSet : public set<MxAtomIdCounter*, MxAtomIdCounterCompare>
|
||||
{};
|
||||
|
||||
#endif //MXATOMIDCOUNTER_H
|
|
@ -38,7 +38,7 @@ void MxOmni::Init()
|
|||
m_eventManager = NULL;
|
||||
m_timer = NULL;
|
||||
m_streamer = NULL;
|
||||
m_unk44 = NULL;
|
||||
m_atomIdCounterSet = NULL;
|
||||
m_unk64 = NULL;
|
||||
}
|
||||
|
||||
|
@ -104,6 +104,8 @@ void MxOmni::SetInstance(MxOmni *instance)
|
|||
// OFFSET: LEGO1 0x100af0c0
|
||||
MxResult MxOmni::Create(MxOmniCreateParam &p)
|
||||
{
|
||||
m_atomIdCounterSet = new MxAtomIdCounterSet();
|
||||
|
||||
if (p.CreateFlags().CreateVariableTable())
|
||||
{
|
||||
MxVariableTable *variableTable = new MxVariableTable();
|
||||
|
@ -129,6 +131,40 @@ MxResult MxOmni::Create(MxOmniCreateParam &p)
|
|||
void MxOmni::Destroy()
|
||||
{
|
||||
// FIXME: Stub
|
||||
|
||||
/*
|
||||
// TODO: private members
|
||||
if (m_notificationManager) {
|
||||
while (m_notificationManager->m_queue->size()) {
|
||||
m_notificationManager->Tickle();
|
||||
}
|
||||
}
|
||||
|
||||
m_notificationManager->m_active = 0;
|
||||
*/
|
||||
|
||||
delete m_eventManager;
|
||||
delete m_soundManager;
|
||||
delete m_musicManager;
|
||||
delete m_videoManager;
|
||||
delete m_streamer;
|
||||
delete m_timer;
|
||||
delete m_objectFactory;
|
||||
delete m_variableTable;
|
||||
delete m_notificationManager;
|
||||
delete m_tickleManager;
|
||||
|
||||
// There could be a tree/iterator function that does this inline
|
||||
if (m_atomIdCounterSet) {
|
||||
while (!m_atomIdCounterSet->empty()) {
|
||||
// Pop each node and delete its value
|
||||
MxAtomIdCounterSet::iterator begin = m_atomIdCounterSet->begin();
|
||||
MxAtomIdCounter *value = *begin;
|
||||
m_atomIdCounterSet->erase(begin);
|
||||
delete value;
|
||||
}
|
||||
delete m_atomIdCounterSet;
|
||||
}
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100b07f0
|
||||
|
@ -162,6 +198,12 @@ MxTimer *Timer()
|
|||
return MxOmni::GetInstance()->GetTimer();
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100acee0
|
||||
MxAtomIdCounterSet *AtomIdCounterSet()
|
||||
{
|
||||
return MxOmni::GetInstance()->GetAtomIdCounterSet();
|
||||
}
|
||||
|
||||
// OFFSET: LEGO1 0x100acef0
|
||||
MxStreamer* Streamer()
|
||||
{
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "mxtimer.h"
|
||||
#include "mxvariabletable.h"
|
||||
#include "mxvideomanager.h"
|
||||
#include "mxatomidcounter.h"
|
||||
|
||||
// VTABLE 0x100dc168
|
||||
// SIZE 0x68
|
||||
|
@ -47,6 +48,7 @@ class MxOmni : public MxCore
|
|||
MxVariableTable* GetVariableTable() const { return this->m_variableTable; }
|
||||
MxMusicManager* GetMusicManager() const { return this->m_musicManager; }
|
||||
MxEventManager* GetEventManager() const { return this->m_eventManager; }
|
||||
MxAtomIdCounterSet* GetAtomIdCounterSet() const { return this->m_atomIdCounterSet; }
|
||||
protected:
|
||||
static MxOmni* g_instance;
|
||||
|
||||
|
@ -63,7 +65,7 @@ class MxOmni : public MxCore
|
|||
MxTimer* m_timer; //0x3C
|
||||
MxStreamer* m_streamer; //0x40
|
||||
|
||||
int m_unk44; // 0x44
|
||||
MxAtomIdCounterSet* m_atomIdCounterSet; // 0x44
|
||||
|
||||
MxCriticalSection m_criticalsection; // 0x48
|
||||
|
||||
|
@ -78,5 +80,6 @@ __declspec(dllexport) MxMusicManager * MusicManager();
|
|||
__declspec(dllexport) MxEventManager * EventManager();
|
||||
__declspec(dllexport) MxNotificationManager * NotificationManager();
|
||||
MxVideoManager * MVideoManager();
|
||||
MxAtomIdCounterSet* AtomIdCounterSet();
|
||||
|
||||
#endif // MXOMNI_H
|
||||
|
|
Loading…
Reference in a new issue