From 05873ad79390c6f0dcd928d7a007bad776b24980 Mon Sep 17 00:00:00 2001 From: AdventureT Date: Fri, 8 Dec 2023 15:51:53 +0100 Subject: [PATCH] !Broken! --- Toshi/Include/TKernel/TArray.h | 287 +++++++++++++++++++++++++++++ Toshi/Include/TKernel/TFreeList.h | 34 +++- Toshi/Include/TKernel/TMemory.h | 1 + Toshi/Include/TKernel/TPCString.h | 11 ++ Toshi/Source/TKernel/TFreeList.cpp | 93 +++++++++- Toshi/Source/TKernel/TMemory.cpp | 9 + Toshi/Source/TKernel/TPCString.cpp | 0 7 files changed, 427 insertions(+), 8 deletions(-) create mode 100644 Toshi/Include/TKernel/TArray.h create mode 100644 Toshi/Include/TKernel/TPCString.h create mode 100644 Toshi/Source/TKernel/TPCString.cpp diff --git a/Toshi/Include/TKernel/TArray.h b/Toshi/Include/TKernel/TArray.h new file mode 100644 index 0000000..dcd64a2 --- /dev/null +++ b/Toshi/Include/TKernel/TArray.h @@ -0,0 +1,287 @@ +#pragma once +#include +#include "TMemory.h" +#include "TSystemTools.h" + +TOSHI_NAMESPACE_BEGIN + +// Borrowed from OpenBarnyard (T2GenericDynamicArray) + +template +class TArray +{ +public: + class Iterator + { + public: + friend TArray; + using Storage = TArray; + + public: + Iterator() + { + m_iIndex = 0; + m_poArray = TNULL; + } + + Iterator(const Iterator& other) + { + m_poArray = other.m_poArray; + m_iIndex = 0; + } + + Iterator(Storage& a_poArray) + { + m_iIndex = 0; + m_poArray = &a_poArray; + } + + Iterator(TINT a_iIndex, Storage& a_poArray) + { + m_iIndex = a_iIndex; + m_poArray = &a_poArray; + } + + void SetCurrentIndex(TINT a_iIndex) const + { + TASSERT(m_poArray); + TASSERT(a_iIndex < m_poArray->GetNumElements()); + m_iIndex = a_iIndex; + } + + TINT GetCurrentIndex() const + { + return m_iIndex; + } + + TINT& IncrementSafe() + { + m_iIndex++; + TASSERT(m_poArray); + + if (m_poArray->m_iNumElements <= m_iIndex || m_iIndex == 0) + m_iIndex = -1; + + return m_iIndex; + } + + void Push(const T& element) + { + TASSERT(m_poArray); + m_poArray->Push(element); + } + + T* operator->() const + { + TASSERT(m_iIndex >= 0); + TASSERT(m_poArray); + TASSERT(m_iIndex < m_poArray->m_iNumElements); + return &m_poArray->m_pData[m_iIndex]; + } + + T& Get() + { + TASSERT(m_iIndex >= 0); + TASSERT(m_poArray); + TASSERT(m_iIndex < m_poArray->m_iNumElements); + return m_poArray->m_pData[m_iIndex]; + } + + bool IsOver() const + { + return (m_iIndex >= m_poArray->GetNumElements() || m_iIndex == -1); + } + + const T& Get() const + { + TASSERT(m_iIndex >= 0); + TASSERT(m_poArray); + TASSERT(m_iIndex < m_poArray->m_iNumElements); + return m_poArray->m_pData[m_iIndex]; + } + + Iterator& operator++() + { + m_iIndex++; + return *this; + } + + Iterator operator++(TINT) + { + Iterator temp = *this; + m_iIndex++; + return temp; + } + + Iterator& operator--() + { + m_iIndex--; + return *this; + } + + Iterator operator--(TINT) + { + Iterator temp = *this; + m_iIndex--; + return temp; + } + + Iterator operator+(TINT a_iValue) const + { + return Iterator(m_iIndex + a_iValue, m_poArray); + } + + Iterator operator-(TINT a_iValue) const + { + return Iterator(m_iIndex - a_iValue, m_poArray); + } + + private: + TINT m_iIndex; // 0x0 + Storage* m_poArray; // 0x4 + }; + +public: + TArray(TINT a_iGrowSize, TINT a_iSize) + { + m_iGrowSize = a_iGrowSize; + m_iNumAllocElements = a_iSize; + m_iNumElements = 0; + + if (m_iNumAllocElements > 0) + { + m_pData = TSTATICCAST(T*, Tmemalign(alignof(T), m_iNumAllocElements * sizeof(T))); + } + else + { + TASSERT(m_iGrowSize != 0); + m_pData = TNULL; + } + } + + ~TArray() + { + if (m_pData) + { + tfree(m_pData); + } + } + + void Clear() + { + if (m_iNumAllocElements < 0) + { + if (m_pData) + { + tfree(m_pData); + m_pData = TNULL; + } + + m_iNumAllocElements = 0; + } + + m_iNumElements = 0; + } + + Iterator Begin() + { + return Iterator((m_iNumElements == 0) ? -1 : 0, *this); + } + + Iterator End() + { + return Iterator(-1, *this); + } + + TINT GetNumElements() const + { + return m_iNumElements; + } + + TINT GetNumAllocElements() const + { + return m_iNumAllocElements; + } + + TINT GetGrowSize() const + { + return m_iGrowSize; + } + + void SetGrowSize(TINT a_iGrowSize) + { + m_iGrowSize = a_iGrowSize; + } + + T* Push(const T& element) + { + GrowBy(1); + return new (&m_pData[m_iNumElements++]) T(element); + } + + T& Pop() + { + TASSERT(m_iNumElements >= 1); + return m_pData[--m_iNumElements]; + } + + T& operator[](TINT a_iIndex) + { + TASSERT(a_iIndex >= 0); + TASSERT(a_iIndex < m_iNumElements); + return m_pData[a_iIndex]; + } + + const T& operator[](TINT a_iIndex) const + { + TASSERT(a_iIndex >= 0); + TASSERT(a_iIndex < m_iNumElements); + return m_pData[a_iIndex]; + } + +private: + void GrowBy(TINT a_iGrowBy) + { + if (m_iNumAllocElements < m_iNumElements + a_iGrowBy) + { + TASSERT(m_iGrowSize != 0); + + + + auto iNewSize = m_iNumAllocElements + m_iGrowSize < m_iNumElements + a_iGrowBy ? TMath::Max(m_iNumAllocElements + m_iGrowSize, m_iNumElements + a_iGrowBy); + Resize(iNewSize); + } + } + + void Resize(TINT a_iNewSize) + { + if (a_iNewSize != 0) + { + T* pNewBuffer = TSTATICCAST(T*, TMemalign(alignof(T), a_iNewSize * sizeof(T))); + size_t uiCopySize = TMath::Min(m_iNumElements, a_iNewSize); + + TUtil::MemCopy(pNewBuffer, m_pData, sizeof(T) * uiCopySize); + + m_iNumAllocElements = a_iNewSize; + TASSERT(m_iNumElements <= m_iNumAllocElements); + + if (m_pData) TFree(m_pData); + m_pData = pNewBuffer; + } + else + { + if (m_pData) TFree(m_pData); + m_pData = TNULL; + m_iNumAllocElements = 0; + m_iNumElements = 0; + } + } + +private: + TINT m_iGrowSize; // 0x0 + TINT m_iNumElements; // 0x4 + TINT m_iNumAllocElements; // 0x8 + T* m_pData; // 0xC +}; + +TOSHI_NAMESPACE_END \ No newline at end of file diff --git a/Toshi/Include/TKernel/TFreeList.h b/Toshi/Include/TKernel/TFreeList.h index 78e76e6..2d2a8ce 100644 --- a/Toshi/Include/TKernel/TFreeList.h +++ b/Toshi/Include/TKernel/TFreeList.h @@ -7,24 +7,44 @@ TOSHI_NAMESPACE_BEGIN class TOSHI_EXPORT TFreeList { public: - struct Node { - Node* pNext = TNULL; + friend class TFreeList; + public: + Node& operator=(const Node& a_rNode) + { + m_pNext = a_rNode.m_pNext; + return *this; + } + protected: + Node* m_pNext = TNULL; }; - TFreeList(); + TFreeList(TUINT a_uiItemSize, TINT a_iInitialSize, TINT a_iGrowSize, TPCHAR a_pcName); + ~TFreeList(); + +protected: + + Node* Allocate(TINT a_iNumber, TUINT a_uiSize); + +public: + TPVOID New(TUINT a_uiSize); + void Delete(TPVOID a_pData); + + void SetCapacity(TINT a_iCapacity); + void SetGrowSize(TINT a_iGrowSize); TINT GetCapacity() const { return m_iCapacity; } TINT GetGrowSize() const { return m_iGrowSize; } TINT GetFreeCount() { return m_iFreeCount; } private: - TFreeList* m_pPrevList; TINT m_iFreeCount; // 0x0 - TUINT m_uiItemSize; - Node m_LastNode; + TINT m_iMaxFreeCount; // 0x4 + TPCHAR m_pcName; // 0x8 TINT m_iCapacity; // 0xC - Node m_RootNode; + TUINT m_uiItemSize; // 0x10 + Node m_oLastNode; // 0x14 + Node m_oRootNode; // 0x18 TINT m_iGrowSize; // 0x1C }; diff --git a/Toshi/Include/TKernel/TMemory.h b/Toshi/Include/TKernel/TMemory.h index ef91bf1..aa31af3 100644 --- a/Toshi/Include/TKernel/TMemory.h +++ b/Toshi/Include/TKernel/TMemory.h @@ -65,4 +65,5 @@ inline static TMemory g_oMemManager; TOSHI_NAMESPACE_END TPVOID TOSHI_EXPORT __stdcall tmalloc(TINT a_iSize, TPCHAR a_pBuffer, TINT a_iUnk); +TPVOID TOSHI_EXPORT __stdcall tmemalign(TINT a_iAlign, TINT a_iSize); void TOSHI_EXPORT __stdcall tfree(TPVOID a_pMem); \ No newline at end of file diff --git a/Toshi/Include/TKernel/TPCString.h b/Toshi/Include/TKernel/TPCString.h new file mode 100644 index 0000000..6c1d8d7 --- /dev/null +++ b/Toshi/Include/TKernel/TPCString.h @@ -0,0 +1,11 @@ +#pragma once +#include "TDebug.h" + +TOSHI_NAMESPACE_BEGIN + +class TOSHI_EXPORT TPCString +{ + +}; + +TOSHI_NAMESPACE_END \ No newline at end of file diff --git a/Toshi/Source/TKernel/TFreeList.cpp b/Toshi/Source/TKernel/TFreeList.cpp index da17fae..d4a84c2 100644 --- a/Toshi/Source/TKernel/TFreeList.cpp +++ b/Toshi/Source/TKernel/TFreeList.cpp @@ -2,7 +2,98 @@ TOSHI_NAMESPACE_USING -TFreeList::TFreeList() +TFreeList::TFreeList(TUINT a_uiItemSize, TINT a_iInitialSize, TINT a_iGrowSize, TPCHAR a_pcName) { + m_iFreeCount = 0; + m_iMaxFreeCount = 0; + m_pcName = a_pcName; + m_iCapacity = 0; + m_uiItemSize = a_uiItemSize; TASSERT(m_iGrowSize >= 0); + TASSERT(a_iInitialSize >= 0); + SetGrowSize(a_iGrowSize); + SetCapacity(a_iInitialSize); +} + +TFreeList::~TFreeList() +{ + for (Node* pNode = m_oRootNode.m_pNext; pNode != TNULL; pNode = m_oRootNode.m_pNext) { + m_oRootNode.m_pNext = pNode->m_pNext; + delete pNode; + } +} + +TFreeList::Node* TFreeList::Allocate(TINT a_iNumber, TUINT a_uiSize) +{ + m_iCapacity += a_iNumber; + m_iFreeCount += a_iNumber; + m_iMaxFreeCount = m_iMaxFreeCount <= m_iFreeCount ? m_iFreeCount : m_iMaxFreeCount; + + Node* pNewNode = (Node*)tmalloc(a_iNumber * a_uiSize + sizeof(Node), TNULL, -1); + + pNewNode->m_pNext = m_oRootNode.m_pNext; + m_oRootNode.m_pNext = pNewNode; + + auto pData = pNewNode + 1; + Node* pNext = TNULL; + + for (TINT i = a_iNumber - 1; i != 0; i--) + { + pData->m_pNext = pNext; + pNext = pData; + + pData = (Node*)(((TUINT*)pData) + a_uiSize); + } + + m_oLastNode.m_pNext = pNext; + return pData; +} + +TPVOID TFreeList::New(TUINT a_uiSize) +{ + if (a_uiSize != m_uiItemSize) { + return operator new (a_uiSize); + } + + Node* pNode = m_oLastNode.m_pNext; + + if (pNode != TNULL) { + m_iFreeCount--; + m_oLastNode.m_pNext = pNode->m_pNext; + return pNode; + } + + TASSERT((0 < m_iGrowSize) && "Tried to grow TFreeList with 0 grow size\n"); + m_iFreeCount--; + return Allocate(m_iGrowSize, a_uiSize); +} + +void TFreeList::Delete(TPVOID a_pData) +{ + Node* pNode = (Node*)a_pData; + + if (m_oLastNode.m_pNext != TNULL) { + pNode->m_pNext = m_oLastNode.m_pNext; + m_oLastNode.m_pNext = pNode; + } + else { + m_oLastNode.m_pNext = pNode; + pNode->m_pNext = TNULL; + } + + m_iFreeCount++; + m_iMaxFreeCount = m_iMaxFreeCount <= m_iFreeCount ? m_iFreeCount : m_iMaxFreeCount; +} + +void TFreeList::SetCapacity(TINT a_iCapacity) +{ + if (a_iCapacity <= m_iCapacity) return; + Node* pNode = Allocate(a_iCapacity - m_iCapacity, m_uiItemSize); + pNode->m_pNext = m_oLastNode.m_pNext; + m_oLastNode.m_pNext = pNode; +} + +void TFreeList::SetGrowSize(TINT a_iGrowSize) +{ + m_iGrowSize = a_iGrowSize < 1 ? 8 : a_iGrowSize; } diff --git a/Toshi/Source/TKernel/TMemory.cpp b/Toshi/Source/TKernel/TMemory.cpp index 6001ae2..749e8d4 100644 --- a/Toshi/Source/TKernel/TMemory.cpp +++ b/Toshi/Source/TKernel/TMemory.cpp @@ -72,6 +72,15 @@ TPVOID TOSHI_EXPORT __stdcall tmalloc(TINT a_iSize, TPCHAR a_pBuffer, TINT a_iUn #endif } +TPVOID TOSHI_EXPORT __stdcall tmemalign(TINT a_iAlign, TINT a_iSize) +{ +#ifdef TOSHI_NOTFINAL + return malloc(a_iSize); +#else + return Toshi::TMemory::GetMemMangager().Alloc(a_iSize, a_iAlign, Toshi::TMemory::GetGlobalBlock(), TNULL, -1); +#endif +} + void TOSHI_EXPORT __stdcall tfree(TPVOID a_pMem) { #ifdef TOSHI_NOTFINAL diff --git a/Toshi/Source/TKernel/TPCString.cpp b/Toshi/Source/TKernel/TPCString.cpp new file mode 100644 index 0000000..e69de29