mirror of
https://github.com/isledecomp/isle.git
synced 2024-11-26 09:38:14 -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/legoworldpresenter.cpp
|
||||||
LEGO1/motorcycle.cpp
|
LEGO1/motorcycle.cpp
|
||||||
LEGO1/mxatomid.cpp
|
LEGO1/mxatomid.cpp
|
||||||
|
LEGO1/mxatomidcounter.cpp
|
||||||
LEGO1/mxaudiopresenter.cpp
|
LEGO1/mxaudiopresenter.cpp
|
||||||
LEGO1/mxautolocker.cpp
|
LEGO1/mxautolocker.cpp
|
||||||
LEGO1/mxbackgroundaudiomanager.cpp
|
LEGO1/mxbackgroundaudiomanager.cpp
|
||||||
|
|
|
@ -14,6 +14,11 @@
|
||||||
// DIsable "nonstandard extension used : 'bool'" warning spam
|
// DIsable "nonstandard extension used : 'bool'" warning spam
|
||||||
#pragma warning( disable : 4237 )
|
#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
|
#define MSVC420_VERSION 1020
|
||||||
|
|
||||||
// STL compatibility.
|
// STL compatibility.
|
||||||
|
@ -22,6 +27,7 @@
|
||||||
#else
|
#else
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <set>
|
||||||
using namespace std;
|
using namespace std;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,97 @@
|
||||||
#include "mxatomid.h"
|
#include "mxatomid.h"
|
||||||
|
#include "mxomni.h"
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x100acf90
|
// 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
|
// OFFSET: LEGO1 0x100acfd0
|
||||||
MxAtomId::~MxAtomId()
|
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
|
// 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;
|
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
|
#define MXATOMID_H
|
||||||
|
|
||||||
#include "mxtypes.h"
|
#include "mxtypes.h"
|
||||||
|
#include "mxatomidcounter.h"
|
||||||
|
|
||||||
enum LookupMode
|
enum LookupMode
|
||||||
{
|
{
|
||||||
|
@ -27,9 +28,13 @@ class MxAtomId
|
||||||
{
|
{
|
||||||
return this->m_internal == other.m_internal;
|
return this->m_internal == other.m_internal;
|
||||||
}
|
}
|
||||||
|
void Clear();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *m_internal;
|
MxAtomIdCounter* GetCounter(const char *, LookupMode);
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
const char *m_internal;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXATOMID_H
|
#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_eventManager = NULL;
|
||||||
m_timer = NULL;
|
m_timer = NULL;
|
||||||
m_streamer = NULL;
|
m_streamer = NULL;
|
||||||
m_unk44 = NULL;
|
m_atomIdCounterSet = NULL;
|
||||||
m_unk64 = NULL;
|
m_unk64 = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +104,8 @@ void MxOmni::SetInstance(MxOmni *instance)
|
||||||
// OFFSET: LEGO1 0x100af0c0
|
// OFFSET: LEGO1 0x100af0c0
|
||||||
MxResult MxOmni::Create(MxOmniCreateParam &p)
|
MxResult MxOmni::Create(MxOmniCreateParam &p)
|
||||||
{
|
{
|
||||||
|
m_atomIdCounterSet = new MxAtomIdCounterSet();
|
||||||
|
|
||||||
if (p.CreateFlags().CreateVariableTable())
|
if (p.CreateFlags().CreateVariableTable())
|
||||||
{
|
{
|
||||||
MxVariableTable *variableTable = new MxVariableTable();
|
MxVariableTable *variableTable = new MxVariableTable();
|
||||||
|
@ -129,6 +131,40 @@ MxResult MxOmni::Create(MxOmniCreateParam &p)
|
||||||
void MxOmni::Destroy()
|
void MxOmni::Destroy()
|
||||||
{
|
{
|
||||||
// FIXME: Stub
|
// 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
|
// OFFSET: LEGO1 0x100b07f0
|
||||||
|
@ -162,6 +198,12 @@ MxTimer *Timer()
|
||||||
return MxOmni::GetInstance()->GetTimer();
|
return MxOmni::GetInstance()->GetTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100acee0
|
||||||
|
MxAtomIdCounterSet *AtomIdCounterSet()
|
||||||
|
{
|
||||||
|
return MxOmni::GetInstance()->GetAtomIdCounterSet();
|
||||||
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x100acef0
|
// OFFSET: LEGO1 0x100acef0
|
||||||
MxStreamer* Streamer()
|
MxStreamer* Streamer()
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "mxtimer.h"
|
#include "mxtimer.h"
|
||||||
#include "mxvariabletable.h"
|
#include "mxvariabletable.h"
|
||||||
#include "mxvideomanager.h"
|
#include "mxvideomanager.h"
|
||||||
|
#include "mxatomidcounter.h"
|
||||||
|
|
||||||
// VTABLE 0x100dc168
|
// VTABLE 0x100dc168
|
||||||
// SIZE 0x68
|
// SIZE 0x68
|
||||||
|
@ -47,6 +48,7 @@ class MxOmni : public MxCore
|
||||||
MxVariableTable* GetVariableTable() const { return this->m_variableTable; }
|
MxVariableTable* GetVariableTable() const { return this->m_variableTable; }
|
||||||
MxMusicManager* GetMusicManager() const { return this->m_musicManager; }
|
MxMusicManager* GetMusicManager() const { return this->m_musicManager; }
|
||||||
MxEventManager* GetEventManager() const { return this->m_eventManager; }
|
MxEventManager* GetEventManager() const { return this->m_eventManager; }
|
||||||
|
MxAtomIdCounterSet* GetAtomIdCounterSet() const { return this->m_atomIdCounterSet; }
|
||||||
protected:
|
protected:
|
||||||
static MxOmni* g_instance;
|
static MxOmni* g_instance;
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ class MxOmni : public MxCore
|
||||||
MxTimer* m_timer; //0x3C
|
MxTimer* m_timer; //0x3C
|
||||||
MxStreamer* m_streamer; //0x40
|
MxStreamer* m_streamer; //0x40
|
||||||
|
|
||||||
int m_unk44; // 0x44
|
MxAtomIdCounterSet* m_atomIdCounterSet; // 0x44
|
||||||
|
|
||||||
MxCriticalSection m_criticalsection; // 0x48
|
MxCriticalSection m_criticalsection; // 0x48
|
||||||
|
|
||||||
|
@ -78,5 +80,6 @@ __declspec(dllexport) MxMusicManager * MusicManager();
|
||||||
__declspec(dllexport) MxEventManager * EventManager();
|
__declspec(dllexport) MxEventManager * EventManager();
|
||||||
__declspec(dllexport) MxNotificationManager * NotificationManager();
|
__declspec(dllexport) MxNotificationManager * NotificationManager();
|
||||||
MxVideoManager * MVideoManager();
|
MxVideoManager * MVideoManager();
|
||||||
|
MxAtomIdCounterSet* AtomIdCounterSet();
|
||||||
|
|
||||||
#endif // MXOMNI_H
|
#endif // MXOMNI_H
|
||||||
|
|
Loading…
Reference in a new issue