From d5cf23badab3347cb38dffec7e762779e4c59e3b Mon Sep 17 00:00:00 2001
From: Christian Semmler <mail@csemmler.com>
Date: Mon, 6 Nov 2023 08:04:51 -0500
Subject: [PATCH] Match MxRegionTopBottom::FUN_100c5280 (#261)

* Match MxRegionTopBottom::FUN_100c5280

* Resolve OtherAppend/Append

* Remove old code
---
 LEGO1/mxdsselectaction.cpp |  4 +--
 LEGO1/mxlist.h             | 68 ++++++++++++++++----------------------
 LEGO1/mxregion.cpp         | 13 +++-----
 LEGO1/mxstringlist.h       |  2 +-
 4 files changed, 36 insertions(+), 51 deletions(-)

diff --git a/LEGO1/mxdsselectaction.cpp b/LEGO1/mxdsselectaction.cpp
index 291a14df..e6ff1895 100644
--- a/LEGO1/mxdsselectaction.cpp
+++ b/LEGO1/mxdsselectaction.cpp
@@ -30,7 +30,7 @@ void MxDSSelectAction::CopyFrom(MxDSSelectAction& p_dsSelectAction)
 	MxStringListCursor cursor(p_dsSelectAction.m_unk0xac);
 	MxString string;
 	while (cursor.Next(string))
-		this->m_unk0xac->OtherAppend(string);
+		this->m_unk0xac->Append(string);
 }
 
 // OFFSET: LEGO1 0x100cbd50
@@ -109,7 +109,7 @@ void MxDSSelectAction::Deserialize(char** p_source, MxS16 p_unk24)
 			if (!strcmp(string.GetData(), *p_source))
 				index = i;
 
-			this->m_unk0xac->OtherAppend(*p_source);
+			this->m_unk0xac->Append(*p_source);
 			*p_source += strlen(*p_source) + 1;
 		}
 
diff --git a/LEGO1/mxlist.h b/LEGO1/mxlist.h
index ed66f9fc..8ef91333 100644
--- a/LEGO1/mxlist.h
+++ b/LEGO1/mxlist.h
@@ -27,9 +27,12 @@ public:
 	}
 
 	T GetValue() { return this->m_obj; }
+	MxListEntry* GetNext() { return m_next; }
+	MxListEntry* GetPrev() { return m_prev; }
 
-	friend class MxList<T>;
-	friend class MxListCursor<T>;
+	void SetValue(T p_obj) { m_obj = p_obj; }
+	void SetNext(MxListEntry* p_next) { m_next = p_next; }
+	void SetPrev(MxListEntry* p_prev) { m_prev = p_prev; }
 
 private:
 	T m_obj;
@@ -69,8 +72,7 @@ public:
 
 	virtual ~MxList();
 
-	void Append(T);
-	void OtherAppend(T p_obj) { _InsertEntry(p_obj, this->m_last, NULL); };
+	void Append(T p_obj) { _InsertEntry(p_obj, this->m_last, NULL); };
 	void DeleteAll();
 	MxU32 GetCount() { return this->m_count; }
 	void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; }
@@ -100,7 +102,7 @@ public:
 	void Destroy();
 	MxBool Next(T& p_obj);
 	MxBool Current(T& p_obj);
-	void Advance();
+	MxBool Advance();
 	MxBool HasMatch() { return m_match != NULL; }
 	void SetValue(T p_obj);
 	void Head() { m_match = m_list->m_first; }
@@ -139,7 +141,7 @@ inline void MxList<T>::DeleteAll()
 		if (!t)
 			break;
 
-		MxListEntry<T>* next = t->m_next;
+		MxListEntry<T>* next = t->GetNext();
 		this->m_customDestructor(t->GetValue());
 		delete t;
 		t = next;
@@ -150,33 +152,18 @@ inline void MxList<T>::DeleteAll()
 	m_first = NULL;
 }
 
-template <class T>
-inline void MxList<T>::Append(T p_newobj)
-{
-	MxListEntry<T>* currentLast = this->m_last;
-	MxListEntry<T>* newEntry = new MxListEntry<T>(p_newobj, currentLast);
-
-	if (currentLast)
-		currentLast->m_next = newEntry;
-	else
-		this->m_first = newEntry;
-
-	this->m_last = newEntry;
-	this->m_count++;
-}
-
 template <class T>
 inline MxListEntry<T>* MxList<T>::_InsertEntry(T p_newobj, MxListEntry<T>* p_prev, MxListEntry<T>* p_next)
 {
 	MxListEntry<T>* newEntry = new MxListEntry<T>(p_newobj, p_prev, p_next);
 
 	if (p_prev)
-		p_prev->m_next = newEntry;
+		p_prev->SetNext(newEntry);
 	else
 		this->m_first = newEntry;
 
 	if (p_next)
-		p_next->m_prev = newEntry;
+		p_next->SetPrev(newEntry);
 	else
 		this->m_last = newEntry;
 
@@ -187,18 +174,15 @@ inline MxListEntry<T>* MxList<T>::_InsertEntry(T p_newobj, MxListEntry<T>* p_pre
 template <class T>
 inline void MxList<T>::_DeleteEntry(MxListEntry<T>* match)
 {
-	MxListEntry<T>** pPrev = &match->m_prev;
-	MxListEntry<T>** pNext = &match->m_next;
-
-	if (match->m_prev)
-		match->m_prev->m_next = *pNext;
+	if (match->GetPrev())
+		match->GetPrev()->SetNext(match->GetNext());
 	else
-		m_first = *pNext;
+		m_first = match->GetNext();
 
-	if (*pNext)
-		(*pNext)->m_prev = *pPrev;
+	if (match->GetNext())
+		match->GetNext()->SetPrev(match->GetPrev());
 	else
-		m_last = *pPrev;
+		m_last = match->GetPrev();
 
 	delete match;
 	this->m_count--;
@@ -207,7 +191,8 @@ inline void MxList<T>::_DeleteEntry(MxListEntry<T>* match)
 template <class T>
 inline MxBool MxListCursor<T>::Find(T p_obj)
 {
-	for (m_match = m_list->m_first; m_match && m_list->Compare(m_match->m_obj, p_obj); m_match = m_match->m_next)
+	for (m_match = m_list->m_first; m_match && m_list->Compare(m_match->GetValue(), p_obj);
+		 m_match = m_match->GetNext())
 		;
 
 	return m_match != NULL;
@@ -223,7 +208,10 @@ inline void MxListCursor<T>::Detach()
 template <class T>
 inline void MxListCursor<T>::Destroy()
 {
-	m_list->m_customDestructor(m_match->GetValue());
+	if (m_match) {
+		m_list->m_customDestructor(m_match->GetValue());
+		Detach();
+	}
 }
 
 template <class T>
@@ -232,7 +220,7 @@ inline MxBool MxListCursor<T>::Next(T& p_obj)
 	if (!m_match)
 		m_match = m_list->m_first;
 	else
-		m_match = m_match->m_next;
+		m_match = m_match->GetNext();
 
 	if (m_match)
 		p_obj = m_match->GetValue();
@@ -250,26 +238,28 @@ inline MxBool MxListCursor<T>::Current(T& p_obj)
 }
 
 template <class T>
-inline void MxListCursor<T>::Advance()
+inline MxBool MxListCursor<T>::Advance()
 {
 	if (!m_match)
 		m_match = m_list->m_first;
 	else
-		m_match = m_match->m_next;
+		m_match = m_match->GetNext();
+
+	return m_match != NULL;
 }
 
 template <class T>
 inline void MxListCursor<T>::SetValue(T p_obj)
 {
 	if (m_match)
-		m_match->m_obj = p_obj;
+		m_match->SetValue(p_obj);
 }
 
 template <class T>
 inline void MxListCursor<T>::Prepend(T p_newobj)
 {
 	if (m_match)
-		m_list->_InsertEntry(p_newobj, m_match->m_prev, m_match);
+		m_list->_InsertEntry(p_newobj, m_match->GetPrev(), m_match);
 }
 
 #endif // MXLIST_H
diff --git a/LEGO1/mxregion.cpp b/LEGO1/mxregion.cpp
index bd2a5f5a..5a37343d 100644
--- a/LEGO1/mxregion.cpp
+++ b/LEGO1/mxregion.cpp
@@ -87,7 +87,7 @@ void MxRegion::vtable18(MxRect32& p_rect)
 
 	if (rectCopy.m_left < rectCopy.m_right && rectCopy.m_top < rectCopy.m_bottom) {
 		MxRegionTopBottom* newTopBottom = new MxRegionTopBottom(rectCopy);
-		m_list->OtherAppend(newTopBottom);
+		m_list->Append(newTopBottom);
 	}
 
 	m_rect.m_left = m_rect.m_left <= p_rect.m_left ? m_rect.m_left : p_rect.m_left;
@@ -147,7 +147,7 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right)
 
 	if (!a.HasMatch()) {
 		MxRegionLeftRight* copy = new MxRegionLeftRight(p_left, p_right);
-		m_leftRightList->OtherAppend(copy);
+		m_leftRightList->Append(copy);
 	}
 	else {
 		if (p_left > leftRight->m_left)
@@ -157,14 +157,9 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right)
 			if (p_right < leftRight->m_right)
 				p_right = leftRight->m_right;
 
-			// TODO: Currently inlined, shouldn't be
 			b = a;
 			b.Advance();
-
-			if (a.HasMatch()) {
-				a.Destroy();
-				a.Detach();
-			}
+			a.Destroy();
 
 			if (!b.Current(leftRight))
 				break;
@@ -178,7 +173,7 @@ void MxRegionTopBottom::FUN_100c5280(MxS32 p_left, MxS32 p_right)
 		}
 		else {
 			MxRegionLeftRight* copy = new MxRegionLeftRight(p_left, p_right);
-			m_leftRightList->OtherAppend(copy);
+			m_leftRightList->Append(copy);
 		}
 	}
 }
diff --git a/LEGO1/mxstringlist.h b/LEGO1/mxstringlist.h
index f92d2b7d..d80c4777 100644
--- a/LEGO1/mxstringlist.h
+++ b/LEGO1/mxstringlist.h
@@ -21,7 +21,7 @@ typedef MxListCursorChild<MxString> MxStringListCursor;
 // MxList<MxString>::~MxList<MxString>
 
 // OFFSET: LEGO1 0x100cbb40 TEMPLATE
-// MxList<MxString>::OtherAppend
+// MxList<MxString>::Append
 
 // OFFSET: LEGO1 0x100cc2d0 TEMPLATE
 // MxList<MxString>::_InsertEntry