mirror of
https://github.com/isledecomp/isle.git
synced 2026-01-20 14:51:15 +00:00
Starting red-black tree for MxAtomId lookup
This commit is contained in:
parent
fa5417f58a
commit
3ae3d2fe20
@ -92,6 +92,7 @@ add_library(lego1 SHARED
|
|||||||
LEGO1/mxaudiopresenter.cpp
|
LEGO1/mxaudiopresenter.cpp
|
||||||
LEGO1/mxautolocker.cpp
|
LEGO1/mxautolocker.cpp
|
||||||
LEGO1/mxbackgroundaudiomanager.cpp
|
LEGO1/mxbackgroundaudiomanager.cpp
|
||||||
|
LEGO1/mxbinarytree.cpp
|
||||||
LEGO1/mxbitmap.cpp
|
LEGO1/mxbitmap.cpp
|
||||||
LEGO1/mxcompositemediapresenter.cpp
|
LEGO1/mxcompositemediapresenter.cpp
|
||||||
LEGO1/mxcompositepresenter.cpp
|
LEGO1/mxcompositepresenter.cpp
|
||||||
|
|||||||
@ -1,9 +1,18 @@
|
|||||||
#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 (!AtomIdTree())
|
||||||
|
return;
|
||||||
|
|
||||||
|
TreeValue *value = try_to_open(p_str, p_mode);
|
||||||
|
m_internal = value->m_str.GetData();
|
||||||
|
value->RefCountInc();
|
||||||
}
|
}
|
||||||
|
|
||||||
// OFFSET: LEGO1 0x100acfd0
|
// OFFSET: LEGO1 0x100acfd0
|
||||||
@ -18,3 +27,46 @@ MxAtomId &MxAtomId::operator=(const MxAtomId &id)
|
|||||||
// TODO
|
// TODO
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100ad210
|
||||||
|
TreeValue *MxAtomId::try_to_open(const char *p_str, LookupMode p_mode)
|
||||||
|
{
|
||||||
|
TreeValue *value = new TreeValue(p_str);
|
||||||
|
TreeNode *node;
|
||||||
|
|
||||||
|
switch (p_mode) {
|
||||||
|
case LookupMode_LowerCase:
|
||||||
|
case LookupMode_LowerCase2:
|
||||||
|
value->m_str.ToLowerCase();
|
||||||
|
break;
|
||||||
|
case LookupMode_UpperCase:
|
||||||
|
value->m_str.ToUpperCase();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
MxBinaryTree *tree = AtomIdTree();
|
||||||
|
// get the closest node that matches the given value
|
||||||
|
node = tree->Search(value);
|
||||||
|
|
||||||
|
// pointer reuse???
|
||||||
|
TreeNode *ptr_reuse = node;
|
||||||
|
|
||||||
|
// is the node an exact match?
|
||||||
|
if (tree->m_root == node ||
|
||||||
|
strcmp(value->m_str.GetData(), node->m_value->m_str.GetData()) > 0) {
|
||||||
|
ptr_reuse = tree->m_root;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr_reuse = ptr_reuse->m_child0;
|
||||||
|
if (ptr_reuse == AtomIdTree()->m_root) {
|
||||||
|
delete value;
|
||||||
|
value = ptr_reuse->m_value;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// LAB_100ad42b
|
||||||
|
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
#ifndef MXATOMID_H
|
#ifndef MXATOMID_H
|
||||||
#define MXATOMID_H
|
#define MXATOMID_H
|
||||||
|
|
||||||
|
#include "mxbinarytree.h"
|
||||||
|
#include "mxstring.h"
|
||||||
#include "mxtypes.h"
|
#include "mxtypes.h"
|
||||||
|
|
||||||
enum LookupMode
|
enum LookupMode
|
||||||
@ -11,6 +13,7 @@ enum LookupMode
|
|||||||
LookupMode_LowerCase2 = 3
|
LookupMode_LowerCase2 = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// SIZE 0x4
|
||||||
class MxAtomId
|
class MxAtomId
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -28,8 +31,11 @@ class MxAtomId
|
|||||||
return this->m_internal == other.m_internal;
|
return this->m_internal == other.m_internal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: belongs here?
|
||||||
|
TreeValue *try_to_open(const char *, LookupMode);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char *m_internal;
|
const char *m_internal;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MXATOMID_H
|
#endif // MXATOMID_H
|
||||||
|
|||||||
240
LEGO1/mxbinarytree.cpp
Normal file
240
LEGO1/mxbinarytree.cpp
Normal file
@ -0,0 +1,240 @@
|
|||||||
|
#include "mxbinarytree.h"
|
||||||
|
|
||||||
|
// 0x101013f0
|
||||||
|
TreeNode *MxBinaryTree::g_Node_Nil = NULL;
|
||||||
|
|
||||||
|
inline void MxBinaryTree::LeftRotate(TreeNode *x)
|
||||||
|
{
|
||||||
|
TreeNode *y = x->m_child1;
|
||||||
|
x->m_child1 = y->m_child0;
|
||||||
|
|
||||||
|
if (y->m_child0 != g_Node_Nil)
|
||||||
|
y->m_child0->m_parent = x;
|
||||||
|
|
||||||
|
y->m_parent = x->m_parent;
|
||||||
|
|
||||||
|
if (m_root->m_parent != x) {
|
||||||
|
if (x == x->m_parent->m_child0) {
|
||||||
|
x->m_parent->m_child0 = y;
|
||||||
|
y->m_child0 = x; //?
|
||||||
|
x->m_parent = y; //?
|
||||||
|
} else {
|
||||||
|
x->m_parent->m_child1 = y;
|
||||||
|
y->m_child1 = x; //?
|
||||||
|
x->m_parent = y; //?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ?
|
||||||
|
y->m_child0 = x;
|
||||||
|
x->m_parent = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void MxBinaryTree::RightRotate(TreeNode *x)
|
||||||
|
{
|
||||||
|
TreeNode *y = x->m_child0;
|
||||||
|
x->m_child0 = y->m_child1;
|
||||||
|
|
||||||
|
if (y->m_child1 != g_Node_Nil)
|
||||||
|
y->m_child1->m_parent = x;
|
||||||
|
|
||||||
|
y->m_parent = x->m_parent;
|
||||||
|
|
||||||
|
if (m_root->m_parent != x) {
|
||||||
|
if (x == x->m_parent->m_child1) {
|
||||||
|
x->m_parent->m_child1 = y;
|
||||||
|
y->m_child1 = x; //?
|
||||||
|
x->m_parent = y; //?
|
||||||
|
} else {
|
||||||
|
x->m_parent->m_child0 = y;
|
||||||
|
y->m_child0 = x; //?
|
||||||
|
x->m_parent = y; //?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//?
|
||||||
|
y->m_child1 = x;
|
||||||
|
x->m_parent = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100ad480
|
||||||
|
void mini_walk(TreeNode* &p_node)
|
||||||
|
{
|
||||||
|
if (p_node->m_color == NODE_COLOR_RED
|
||||||
|
&& p_node->m_parent->m_parent == p_node) {
|
||||||
|
p_node = p_node->m_child1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *t = p_node->m_child0;
|
||||||
|
if (t != MxBinaryTree::g_Node_Nil) {
|
||||||
|
|
||||||
|
// wonky
|
||||||
|
while (1) {
|
||||||
|
if (t->m_child1 == MxBinaryTree::g_Node_Nil)
|
||||||
|
break;
|
||||||
|
t = t->m_child1;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_node = t;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *u = p_node->m_parent;
|
||||||
|
TreeNode *v = p_node;
|
||||||
|
while (u != v) {
|
||||||
|
p_node = u;
|
||||||
|
v = u;
|
||||||
|
u = u->m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
p_node = u;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100ad4d0
|
||||||
|
void MxBinaryTree::FUN_100ad4d0(TreeNode **p_output, TreeNode *p_leaf, TreeNode *p_parent, TreeValue *&p_value)
|
||||||
|
{
|
||||||
|
TreeNode *node = new TreeNode(p_parent, NODE_COLOR_RED);
|
||||||
|
node->m_child0 = g_Node_Nil;
|
||||||
|
node->m_child1 = g_Node_Nil;
|
||||||
|
|
||||||
|
// TODO: ???
|
||||||
|
if (node->m_value) {
|
||||||
|
node->m_value = p_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->m_p3++; // node count?
|
||||||
|
|
||||||
|
// if tree is NOT empty
|
||||||
|
// if param_2 is tree_nil (always true I think?)
|
||||||
|
//
|
||||||
|
if (this->m_root != p_parent
|
||||||
|
&& p_leaf == MxBinaryTree::g_Node_Nil
|
||||||
|
&& strcmp(p_value->m_str.GetData(),
|
||||||
|
p_parent->m_value->m_str.GetData()) <= 0) {
|
||||||
|
p_parent->m_child1 = node;
|
||||||
|
|
||||||
|
if (m_root->m_child1 == p_parent)
|
||||||
|
m_root->m_child1 = node;
|
||||||
|
} else {
|
||||||
|
p_parent->m_child0 = node;
|
||||||
|
|
||||||
|
if (m_root != p_parent && m_root->m_child0 == p_parent) {
|
||||||
|
m_root->m_child0 = p_parent;
|
||||||
|
} else {
|
||||||
|
m_root->m_parent = node;
|
||||||
|
m_root->m_child1 = node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LAB_100ad593
|
||||||
|
// rebalance??
|
||||||
|
TreeNode *cur = node;
|
||||||
|
while (m_root->m_parent != cur) {
|
||||||
|
TreeNode *parent = cur->m_parent;
|
||||||
|
|
||||||
|
if (parent->m_color != NODE_COLOR_RED)
|
||||||
|
break;
|
||||||
|
|
||||||
|
TreeNode *grandparent = parent->m_parent;
|
||||||
|
TreeNode *uncle = grandparent->m_child0;
|
||||||
|
|
||||||
|
if (uncle == parent) {
|
||||||
|
// wrong uncle
|
||||||
|
uncle = grandparent->m_child1;
|
||||||
|
|
||||||
|
if (uncle->m_color != NODE_COLOR_RED) {
|
||||||
|
|
||||||
|
// 100ad5d3
|
||||||
|
if (parent->m_child1 == cur) {
|
||||||
|
cur = parent;
|
||||||
|
LeftRotate(cur);
|
||||||
|
// rotate.
|
||||||
|
/*
|
||||||
|
parent->m_child1 = parent->m_child1->m_child0;
|
||||||
|
|
||||||
|
// 100ad5e2
|
||||||
|
if (parent->m_child1 != g_Node_Nil)
|
||||||
|
parent->m_child1->m_parent = cur;
|
||||||
|
|
||||||
|
parent->m_child1->m_parent = grandparent;
|
||||||
|
if (m_root->m_parent == cur || grandparent->m_child0 == cur)
|
||||||
|
grandparent->m_child1 = parent;
|
||||||
|
else
|
||||||
|
grandparent->m_child0 = parent;
|
||||||
|
|
||||||
|
parent->m_child0 = cur;
|
||||||
|
grandparent->m_child0 = parent;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
// LAB_100ad60f
|
||||||
|
cur->m_parent->m_color = NODE_COLOR_BLACK;
|
||||||
|
cur->m_parent->m_parent->m_color = NODE_COLOR_RED;
|
||||||
|
RightRotate(cur->m_parent->m_parent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// LAB_100ad67f
|
||||||
|
if (uncle->m_color != NODE_COLOR_RED) {
|
||||||
|
if (parent->m_child0 == cur) {
|
||||||
|
cur = parent;
|
||||||
|
RightRotate(cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
// LAB_100ad60f
|
||||||
|
cur->m_parent->m_color = NODE_COLOR_BLACK;
|
||||||
|
cur->m_parent->m_parent->m_color = NODE_COLOR_RED;
|
||||||
|
LeftRotate(cur->m_parent->m_parent);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LAB_100ad72c
|
||||||
|
parent->m_color = NODE_COLOR_BLACK;
|
||||||
|
uncle->m_color = NODE_COLOR_BLACK;
|
||||||
|
parent->m_parent->m_color = NODE_COLOR_RED;
|
||||||
|
|
||||||
|
cur = parent->m_parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_root->m_parent->m_color = NODE_COLOR_BLACK;
|
||||||
|
*p_output = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100ad780
|
||||||
|
TreeNode *MxBinaryTree::Search(TreeValue*& p_value)
|
||||||
|
{
|
||||||
|
TreeNode *node_match = m_root;
|
||||||
|
TreeNode *t_node = node_match->m_parent;
|
||||||
|
|
||||||
|
while (t_node != g_Node_Nil) {
|
||||||
|
int result = strcmp(t_node->m_value->m_str.GetData(), p_value->m_str.GetData());
|
||||||
|
|
||||||
|
if (result <= 0) {
|
||||||
|
// if strings equal or less than search string
|
||||||
|
// closest match?
|
||||||
|
// it either does match or is where we will insert the new node.
|
||||||
|
node_match = t_node;
|
||||||
|
t_node = t_node->m_child0;
|
||||||
|
} else {
|
||||||
|
t_node = t_node->m_child1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node_match;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100ad7f0
|
||||||
|
void TreeValue::RefCountInc()
|
||||||
|
{
|
||||||
|
m_t0++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100ad800
|
||||||
|
void TreeValue::RefCountDec()
|
||||||
|
{
|
||||||
|
if (m_t0)
|
||||||
|
m_t0--;
|
||||||
|
}
|
||||||
71
LEGO1/mxbinarytree.h
Normal file
71
LEGO1/mxbinarytree.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#ifndef MXBINARYTREE_H
|
||||||
|
#define MXBINARYTREE_H
|
||||||
|
|
||||||
|
#include "mxstring.h"
|
||||||
|
|
||||||
|
// TODO: enum instead?
|
||||||
|
#define NODE_COLOR_RED 0
|
||||||
|
#define NODE_COLOR_BLACK 1
|
||||||
|
|
||||||
|
// SIZE 0x14
|
||||||
|
class TreeValue {
|
||||||
|
public:
|
||||||
|
TreeValue(const char *p_str)
|
||||||
|
{
|
||||||
|
m_str = p_str;
|
||||||
|
m_t0 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RefCountInc();
|
||||||
|
void RefCountDec();
|
||||||
|
|
||||||
|
MxString m_str;
|
||||||
|
MxU16 m_t0;
|
||||||
|
MxU16 m_t1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// SIZE 0x14
|
||||||
|
class TreeNode {
|
||||||
|
public:
|
||||||
|
TreeNode(TreeNode *p_parent, int p_color)
|
||||||
|
{
|
||||||
|
m_parent = p_parent;
|
||||||
|
m_color = p_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *m_child0; // +0 // string sorts after
|
||||||
|
TreeNode *m_parent; // +4 // parent node
|
||||||
|
TreeNode *m_child1; // +8 // string sorts before
|
||||||
|
TreeValue *m_value; // +c
|
||||||
|
int m_color; // +10 // BLACK or RED.
|
||||||
|
};
|
||||||
|
|
||||||
|
// SIZE 0x10
|
||||||
|
class MxBinaryTree
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Dummy node to represent null value.
|
||||||
|
static TreeNode *g_Node_Nil;
|
||||||
|
MxBinaryTree()
|
||||||
|
{
|
||||||
|
if (!g_Node_Nil) {
|
||||||
|
g_Node_Nil = new TreeNode(NULL, NODE_COLOR_BLACK);
|
||||||
|
g_Node_Nil->m_child0 = NULL;
|
||||||
|
g_Node_Nil->m_child1 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_root = new TreeNode(g_Node_Nil, NODE_COLOR_RED);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LeftRotate(TreeNode *);
|
||||||
|
void RightRotate(TreeNode *);
|
||||||
|
void FUN_100ad4d0(TreeNode **, TreeNode *, TreeNode *, TreeValue *&);
|
||||||
|
TreeNode *Search(TreeValue *&);
|
||||||
|
|
||||||
|
int m_p0; // +0
|
||||||
|
TreeNode *m_root; // +4
|
||||||
|
int m_p2; // +8
|
||||||
|
int m_p3; // +c
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //MXBINARYTREE_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_atomIdTree = 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_atomIdTree = new MxBinaryTree();
|
||||||
|
|
||||||
if (p.CreateFlags().CreateTimer())
|
if (p.CreateFlags().CreateTimer())
|
||||||
{
|
{
|
||||||
MxTimer *timer = new MxTimer();
|
MxTimer *timer = new MxTimer();
|
||||||
@ -153,6 +155,12 @@ MxTimer *Timer()
|
|||||||
return MxOmni::GetInstance()->GetTimer();
|
return MxOmni::GetInstance()->GetTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OFFSET: LEGO1 0x100acee0
|
||||||
|
MxBinaryTree *AtomIdTree()
|
||||||
|
{
|
||||||
|
return MxOmni::GetInstance()->GetAtomIdTree();
|
||||||
|
}
|
||||||
|
|
||||||
// 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 "mxbinarytree.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; }
|
||||||
|
MxBinaryTree* GetAtomIdTree() const { return this->m_atomIdTree; }
|
||||||
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
|
MxBinaryTree *m_atomIdTree; // 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();
|
||||||
|
MxBinaryTree *AtomIdTree();
|
||||||
|
|
||||||
#endif // MXOMNI_H
|
#endif // MXOMNI_H
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user