diff --git a/configure.py b/configure.py index 5913d0f8b..bfa8dba6c 100755 --- a/configure.py +++ b/configure.py @@ -920,7 +920,7 @@ config.libs = [ [ Object(Matching, "JSystem/JGadget/binary.cpp"), Object(Matching, "JSystem/JGadget/linklist.cpp"), - Object(NonMatching, "JSystem/JGadget/std-vector.cpp"), + Object(Equivalent, "JSystem/JGadget/std-vector.cpp"), # weak func order ], ), JSystemLib( diff --git a/include/JSystem/JGadget/allocator.h b/include/JSystem/JGadget/allocator.h index 08498d8f1..7b110acfa 100644 --- a/include/JSystem/JGadget/allocator.h +++ b/include/JSystem/JGadget/allocator.h @@ -6,19 +6,35 @@ namespace JGadget { template struct TAllocator { - // TODO: this constructor declaration needs to be removed in order to match TFunctionValue_composite's constructor + // TODO: This explicit ctor needs to be removed in order to match TFunctionValue_composite's constructor // in functionvalue.cpp, and in order to get the @564 struct literal to appear in the .sbss section of that TU. - // however, removing this declaration also causes that bss literal to appear in hundreds of other TUs it shouldn't. - TAllocator(); + // However, removing this definition also causes that bss literal to appear in other TUs it shouldn't. + // This seems related to the 16 1-byte weak bss symbols that appear in a ton of different TUs (@936 to @1036) + // as this literal also has alignment 1 in the debug maps but alignment for in non-debug maps. + // Specifically it's the JGadget::TAllocator() inside of TFunctionValueAttribute_refer that creates the literal. + TAllocator() {} - // TODO - void AllocateRaw(u32) {} - void DeallocateRaw(void*) {} - void allocate(u32, const void*) {} - void deallocate(T*, u32) {} - void destroy(T*) {} + T* allocate(u32 count, const void *param_2) { + return AllocateRaw(count * sizeof(T)); + } - /* 0x00 */ u8 _00; + T* AllocateRaw(u32 size) { + return (T*)operator new(size); + } + + void deallocate(T* mem, u32 size) { + DeallocateRaw(mem); + } + + void DeallocateRaw(void* mem) { + delete (T*)mem; + } + + void destroy(T* p) { + // JUT_ASSERT(68, p!=0); + } + + /* 0x00 */ u8 mAllocator; }; typedef TAllocator TVoidAllocator; diff --git a/include/JSystem/JGadget/vector.h b/include/JSystem/JGadget/vector.h index f690b4857..a8312e006 100644 --- a/include/JSystem/JGadget/vector.h +++ b/include/JSystem/JGadget/vector.h @@ -1,8 +1,9 @@ -#ifndef JGADGET_VECTOR_H -#define JGADGET_VECTOR_H +#ifndef _JSYSTEM_JGADGET_VECTOR_H +#define _JSYSTEM_JGADGET_VECTOR_H #include "JSystem/JGadget/allocator.h" -#include "dolphin/types.h" +#include "algorithm.h" +#include "msl_memory.h" namespace JGadget { namespace vector { @@ -12,69 +13,244 @@ typedef u32 (*ExtendFunc)(u32, u32, u32); } // namespace vector -template class Allocator> +template /***/> struct TVector { - // struct Destructed_deallocate_ { - // ~Destructed_deallocate_(); // unused/inlined - // }; + struct TDestructed_deallocate_ { + TDestructed_deallocate_(JGadget::TAllocator& alloc, T* pointer) + { + mAllocator = &alloc; + mPointer = pointer; + } - // TVector(u32, const T&, const Allocator&); + ~TDestructed_deallocate_() { mAllocator->deallocate(mPointer, 0); } - // TVector(Allocator alloc) - // { - // _00 = alloc._00; - // _04 = nullptr; - // mBegin = nullptr; - // mEnd = nullptr; - // mExtend = vector::extend_default; - // } + void set(T* p) { mPointer = p; } - ~TVector(); + Allocator* mAllocator; + T* mPointer; + }; + + ~TVector() { + Confirm(); + clear(); + delete mBegin; + } + + // void insert(T*, u32, const T&); + void insert(T* position, u32 count, T const& value) + { + if (!count) { + return; + } + + void** v = Insert_raw(position, count); // insert `count` values before element at `position` + + if (v != this->mEnd) { + for (int i = 0; i != count; i++) { + if (v) { + *v = value; + } + v++; + } + } + } + + void** Insert_raw(T* position, u32 count) + { + // purpose: to make space for `count` many elements at the supplied location + // returns: pointer to location for new items + + T* const pFirst = position; + + // JUT_DEBUG_ASSERT((mBegin<=pItFirst_)&&(pItFirst_<=mEnd), 0x1be); + + // it's assumed the pointer is to something already in the vector, or pointing to the end + + if (count == 0) { + return position; + } + + // can we fit in the space already allocated? + if (count + size() <= mCapacity) { + + // get the theoretical new end + void** newEnd = pFirst + count; + + // if there exists items in the current vector past where we will insert these items + // then we need to move them to be at the end of the vector + if (newEnd < mEnd) { + + // get a pointer to the `count` many values that need to be pushed to the end + void** pOverwrittenValues = mEnd - count; + + // copy `count` many values to the end of the vector + std::uninitialized_copy(pOverwrittenValues, mEnd, mEnd); + + // copy the remaining values that need to be shifted + // copying backwards so we don't move a value into the range we're copying from, erasing data + std::copy_backward(pFirst, pOverwrittenValues, mEnd); + + // destroy everything from pFirst -> newEnd, this treats the inserted items as "uninitialized" + DestroyElement_(pFirst, newEnd); + + // increment count + mEnd += count; + + // return pointer to new items + return pFirst; + } else { + // position + count >= mEnd + // else our values that we want to add will write beyond the current mEnd + + // copy the values that exist at our pointer to the newEnd, which is position + count, making room for our `count` many + // items + std::uninitialized_copy(pFirst, mEnd, newEnd); + + // uninitialize the values that used to be there + DestroyElement_(pFirst, mEnd); + + // increment count + mEnd += count; + + // return pointer to new items + return position; + } + } + + // count + size() > mCapacity + // we need more space + + // figure out how much space we'll need + u32 newSize = GetSize_extend_(count); + + // allocate that space + void** newDataPointer = mAllocator.allocate(newSize, 0); + + // make sure that data was actually allocated + if (!newDataPointer) { + // return end pointer so we know not to actually assign any values + return end(); + } + + // this struct will deallocate the specified data pointer when destroyed + // If we end up throwing an exception, it'll deallocate our new data pointer, no leaks! + TDestructed_deallocate_ destructionDeallocator(mAllocator, newDataPointer); + + // copy all the beginning of our data up to our pointer to the new data + void** const endOfCopy = std::uninitialized_copy(mBegin, pFirst, newDataPointer); + + // copy the rest of the data to fit at the end of our new data + // this leaves a gap of `count` many items in our new data + std::uninitialized_copy(pFirst, mEnd, endOfCopy + count); + + // destroy all our current elements, the other elements should be living in the new data + // and we're about to deallocate our + DestroyElement_all_(); + + // everything should be set, so now we can deallocate our old data pointer + // when this func exits + destructionDeallocator.set(mBegin); + + // set our new vector member variables + mEnd = newDataPointer + (mEnd - mBegin + count); + mBegin = newDataPointer; + mCapacity = newSize; + + // return where the gap of `count` many items lives + return endOfCopy; + } + + void** insert(T* position, const T& value) + { + u32 posOffset = position - mBegin; + // insert one value of `value` at `position` + insert(position, 1, value); + return mBegin + posOffset; // return pointer to new value at position + } - void insert(T*, u32, const T&); - void Insert_raw(T*, u32); - void insert(T*, const T&); void assign(u32, const T&); void resize(u32, const T&); void Resize_raw(u32); - void operator=(const TVector& rhs); + void operator=(const TVector& rhs); - inline u32 size() const { - if (mBegin == NULL) { + size_t GetSize_extend_(size_t count) const + { + u32 oldSize = size(); + u32 neededNewSpace = oldSize + count; + u32 extendedSize = mExtend(capacity(), oldSize, count); + + return neededNewSpace > extendedSize ? neededNewSpace : extendedSize; + } + + T* begin() { return mBegin; } + T* const begin() const { return mBegin; } + T* end() { return mEnd; } + T* const end() const { return mEnd; } + + size_t capacity() const { return mCapacity; } + + inline size_t size() const + { + if (begin() == NULL) { return 0; } - return ((int)mEnd - (int)mBegin) / 4; } - void** begin() { return mBegin; } - void** const begin() const { return mBegin; } - void** end() { return mEnd; } - void** const end() const { return mEnd; } + void DestroyElement_(T* pFirst, T* pLast) + { + void** iter = pFirst; + while (iter != pLast) { + mAllocator.destroy(iter); + ++iter; + } + } + void DestroyElement_all_() { DestroyElement_(mBegin, mEnd); } - /* 0x04 */ u8 _00; - /* 0x08 */ void** mBegin; - /* 0x0C */ void** mEnd; - /* 0x10 */ void** _0C; - /* 0x14 */ vector::ExtendFunc mExtend; + void Confirm() const {} + + void clear() { + erase(begin(), end()); + } + T* erase(T* start, T* end) { + T* ppvVar3 = std::copy(end, TVector::end(), start); + DestroyElement_(ppvVar3, mEnd); + mEnd = ppvVar3; + return start; + } + + /* 0x00 */ Allocator mAllocator; + /* 0x04 */ T* mBegin; + /* 0x08 */ T* mEnd; + /* 0x0C */ size_t mCapacity; + /* 0x10 */ vector::ExtendFunc mExtend; }; -struct TVector_pointer_void : TVector { - TVector_pointer_void(const JGadget::TAllocator&); +// clang-format off +struct TVector_pointer_void : public TVector > { + TVector_pointer_void(const JGadget::TAllocator& allocator); + TVector_pointer_void(u32, void* const&, const JGadget::TAllocator& allocator); // unused/inlined ~TVector_pointer_void(); - void insert(void**, void* const&); - void erase(void**, void**); + void** erase(void**, void**); + void** insert(void**, void* const&); void clear() { erase(begin(), end()); } - void push_back(const void*& ref) { insert(end(), (void* const&)ref); } + void push_back(const void*& value) { insert(end(), (void* const&)value); } + + /* 0x00 */ /* TVector */ }; +// clang-format on template -struct TVector_pointer : TVector_pointer_void { - TVector_pointer(const TAllocator& allocator) : TVector_pointer_void(allocator) {} - ~TVector_pointer() {} +struct TVector_pointer : public TVector_pointer_void { + TVector_pointer(const TAllocator& allocator) + : TVector_pointer_void(allocator) + { + } + + ~TVector_pointer() { } const T* begin() const { return (const T*)TVector_pointer_void::begin(); } T* begin() { return (T*)TVector_pointer_void::begin(); } @@ -82,11 +258,144 @@ struct TVector_pointer : TVector_pointer_void { const T* end() const { return (const T*)TVector_pointer_void::end(); } T* end() { return (T*)TVector_pointer_void::end(); } - void push_back(const T& ref) { - static_cast(this)->push_back((const void*&)ref); - } + void push_back(const T& value) { TVector_pointer_void::push_back((const void*&)value); } + + /* 0x00 */ /* TVector_pointer_void */ }; -} // namespace JGadget +// clang-format off +typedef JGadget::TVector > TVPVBase; +// clang-format on -#endif /* JGADGET_VECTOR_H */ +// template <> +// void TVPVBase::insert(void** values, u32 count, void* const& defaultValue) +// { +// if (!count) { +// return; +// } + +// void** v = Insert_raw(values, count); + +// if (v != this->mEnd) { +// for (int i = 0; i != count; i++) { +// if (v) { +// *v = defaultValue; +// } +// v++; +// } +// } +// } + +/** + * @note Address: 0x80027718 + * @note Size: 0x470 + */ +template <> +void** TVPVBase::Insert_raw(void** pItFirst, u32 count) +{ + // purpose: to make space for `count` many elements at the supplied location + // returns: pointer to location for new items + + void** const pItFirst_ = pItFirst; + + // JUT_DEBUG_ASSERT((mBegin<=pItFirst_)&&(pItFirst_<=mEnd), 0x1be); + + // it's assumed the pointer is to something already in the vector, or pointing to the end + + if (count == 0) { + return pItFirst; + } + + // can we fit in the space already allocated? + if (count + size() <= mCapacity) { + + // get the theoretical new end + void** newEnd = pItFirst_ + count; + + // if there exists items in the current vector past where we will insert these items + // then we need to move them to be at the end of the vector + if (newEnd < mEnd) { + + // get a pointer to the `count` many values that need to be pushed to the end + void** pOverwrittenValues = mEnd - count; + + // copy `count` many values to the end of the vector + std::uninitialized_copy(pOverwrittenValues, mEnd, mEnd); + + // copy the remaining values that need to be shifted + // copying backwards so we don't move a value into the range we're copying from, erasing data + std::copy_backward(pItFirst_, pOverwrittenValues, mEnd); + + // destroy everything from pItFirst_ -> newEnd, this treats the inserted items as "uninitialized" + DestroyElement_(pItFirst_, newEnd); + + // increment count + mEnd += count; + + // return pointer to new items + return pItFirst; + } else { + // pItFirst + count >= mEnd + // else our values that we want to add will write beyond the current mEnd + + // copy the values that exist at our pointer to the newEnd, which is pItFirst + count, making room for our `count` many + // items + std::uninitialized_copy(pItFirst_, mEnd, newEnd); + + // uninitialize the values that used to be there + DestroyElement_(pItFirst_, mEnd); + + // increment count + mEnd += count; + + // return pointer to new items + return pItFirst; + } + } + + // count + size() > mCapacity + // we need more space + + // figure out how much space we'll need + u32 newSize = GetSize_extend_(count); + + // allocate that space + void** newDataPointer = mAllocator.allocate(newSize, 0); + + // make sure that data was actually allocated + if (!newDataPointer) { + // return end pointer? + return end(); + } + + // this struct will deallocate the specified data pointer when destroyed + // If we end up throwing an exception, it'll deallocate our new data pointer, no leaks! + TDestructed_deallocate_ destructionDeallocator(mAllocator, newDataPointer); + + // copy all the beginning of our data up to our pointer to the new data + void** const endOfCopy = std::uninitialized_copy(mBegin, pItFirst_, newDataPointer); + + // copy the rest of the data to fit at the end of our new data + // this leaves a gap of `count` many items in our new data + std::uninitialized_copy(pItFirst_, mEnd, endOfCopy + count); + + // destroy all our current elements, the other elements should be living in the new data + // and we're about to deallocate our + DestroyElement_all_(); + + // everything should be set, so now we can deallocate our old data pointer + // when this func exits + destructionDeallocator.set(mBegin); + + // set our new vector member variables + mEnd = newDataPointer + (mEnd - mBegin + count); + mBegin = newDataPointer; + mCapacity = newSize; + + // return where the gap of `count` many items lives + return endOfCopy; +} + +} // namespace JGadget + +#endif diff --git a/src/JSystem/JGadget/std-vector.cpp b/src/JSystem/JGadget/std-vector.cpp index 6d5630d63..43711edcb 100644 --- a/src/JSystem/JGadget/std-vector.cpp +++ b/src/JSystem/JGadget/std-vector.cpp @@ -7,7 +7,7 @@ #include "dolphin/types.h" namespace JGadget { - + /* 802BFF14-802BFF1C .text extend_default__Q27JGadget6vectorFUlUlUl */ u32 vector::extend_default(u32, u32 param_2, u32) { return param_2 * 2; @@ -15,26 +15,24 @@ u32 vector::extend_default(u32, u32 param_2, u32) { /* 802BFF1C-802BFF48 .text __ct__Q27JGadget20TVector_pointer_voidFRCQ27JGadget14TAllocator */ TVector_pointer_void::TVector_pointer_void(const TAllocator& allocator) { - _00 = allocator._00; + mAllocator = allocator; mBegin = NULL; mEnd = mBegin; - _0C = NULL; + mCapacity = 0; mExtend = vector::extend_default; } /* 802BFF48-802BFFF0 .text __dt__Q27JGadget20TVector_pointer_voidFv */ -TVector_pointer_void::~TVector_pointer_void() { - /* Nonmatching */ -} +TVector_pointer_void::~TVector_pointer_void() {} /* 802BFFF0-802C0010 .text insert__Q27JGadget20TVector_pointer_voidFPPvRCPv */ -void TVector_pointer_void::insert(void**, void* const&) { - /* Nonmatching */ +void** TVector_pointer_void::insert(void** position, void* const& value) { + return TVector::insert(position, value); } /* 802C0010-802C0068 .text erase__Q27JGadget20TVector_pointer_voidFPPvPPv */ -void TVector_pointer_void::erase(void**, void**) { - /* Nonmatching */ +void** TVector_pointer_void::erase(void** start, void** end) { + return TVector::erase(start, end); } // /* 802C0068-802C00D8 .text insert__Q27JGadget38TVector>FPPvUlRCPv */ diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/algorithm.h b/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/algorithm.h index 9ffe91876..448ddc0fb 100644 --- a/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/algorithm.h +++ b/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/algorithm.h @@ -1,9 +1,29 @@ #ifndef MSL_ALGORITHM_H_ #define MSL_ALGORITHM_H_ +#include + namespace std { template -ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val); +ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T& val) { + typedef typename iterator_traits::difference_type difference_type; + difference_type len = std::distance(first, last); + + while (len > 0) { + ForwardIterator i = first; + difference_type step = len / 2; + std::advance(i, step); + + if (*i < val) { + first = ++i; + len -= step + 1; + } else { + len = step; + } + } + + return first; +} template ForwardIterator upper_bound(ForwardIterator first, ForwardIterator last, const T& val); @@ -38,11 +58,62 @@ void __fill(ForwardIt first, ForwardIt last, const T& value, std::random_access_ */ template -void fill(ForwardIt first, ForwardIt last, const T& value) { +inline void fill(ForwardIt first, ForwardIt last, const T& value) { for (; first != last; ++first){ *first = value; } } + +template +inline OutputIt copy(InputIt first, InputIt last, + OutputIt d_first) { + for (; first < last; ++first, ++d_first) { + *d_first = *first; + } + return d_first; +} + +template +inline BidirectionalIterator2 copy_backward(BidirectionalIterator1 first, BidirectionalIterator1 last, BidirectionalIterator2 result) { + while (last != first) + *--result = *--last; + return result; +} + +template +struct __copy_backward +{ + static T* copy_backward(T* first, T* last, T* result) + { + while (last > first) + *--result = *--last; + return result; + } +}; + +template +struct __copy_backward +{ + static T* copy_backward(T* first, T* last, T* result) + { +#ifdef DEBUG + size_t n = static_cast(last - first); + result -= n; + memmove(result, first, n*sizeof(T)); + return result; +#else + while (last > first) + *--result = *--last; + return result; +#endif + } +}; + +template +inline T* copy_backward(T* first, T* last, T* result) { + return __copy_backward::copy_backward(first, last, result); +} + } // namespace std #endif diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/iterator.h b/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/iterator.h new file mode 100644 index 000000000..44d88a3ba --- /dev/null +++ b/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/iterator.h @@ -0,0 +1,100 @@ +#ifndef ITERATOR_H +#define ITERATOR_H +#ifndef MSL_ITERATOR_H_ +#define MSL_ITERATOR_H_ + +#include "stddef.h" + +namespace std { +struct input_iterator_tag {}; +struct output_iterator_tag {}; +struct forward_iterator_tag : public input_iterator_tag {}; +struct bidirectional_iterator_tag : public forward_iterator_tag {}; +struct random_access_iterator_tag : public bidirectional_iterator_tag {}; + +template +struct iterator_traits { + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; + typedef typename Iterator::iterator_category iterator_category; +}; + +template +struct iterator_traits { + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef random_access_iterator_tag iterator_category; +}; + +template +inline void __advance(InputIterator& i, Distance n, input_iterator_tag) { + for (; n > 0; --n) + ++i; +} + +template +inline void __advance(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag) { + if (n >= 0) + for (; n > 0; --n) + ++i; + else + for (; n < 0; ++n) + --i; +} + +template +inline void __advance(RandomAccessIterator& i, Distance n, random_access_iterator_tag) { + i += n; +} + +template +inline void advance(InputIterator& i, Distance n) { + __advance(i, n, typename iterator_traits::iterator_category()); +} + +// TODO: combine this with above later +template +inline void advance_fake(InputIt& it, Distance n) { + while (n > 0) { + --n; + ++it; + } +} + +template +inline typename iterator_traits::difference_type +__distance(InputIterator first, InputIterator last, input_iterator_tag) { + typename iterator_traits::difference_type result = 0; + for (; first != last; ++first) + ++result; + return result; +} + +template +inline typename iterator_traits::difference_type +__distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag) { + return last - first; +} + +template +inline typename iterator_traits::difference_type distance(InputIterator first, + InputIterator last) { + return __distance(first, last, typename iterator_traits::iterator_category()); +} + +// This needs to be defined with gcc concepts or something similar. Workaround. +template +inline void advance_pointer(InputIt& it, Distance n) { + it += n; +} + +} // namespace std + +#endif + + +#endif /* ITERATOR_H */ diff --git a/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/msl_memory.h b/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/msl_memory.h new file mode 100644 index 000000000..e2fc73fd1 --- /dev/null +++ b/src/PowerPC_EABI_Support/MSL/MSL_C++/MSL_Common/Include/msl_memory.h @@ -0,0 +1,58 @@ +#ifndef MSL_MEMORY_H +#define MSL_MEMORY_H +#ifndef MSL_MEMORY_H_ +#define MSL_MEMORY_H_ + +#include "stddef.h" + +namespace std { + +template +inline ForwardIt uninitialized_fill_n(ForwardIt first, Size count, const T& value) { + for (; count--; ++first) { + if (first != NULL) { + *first = value; + } + } + return first; +} + +template +inline ForwardIterator __uninitialized_copy(InputIterator first, InputIterator last, ForwardIterator result) { + ForwardIterator __save = result; + + for (; first != last; ++first, ++result) { + *result = *first; + } + return result; +} + +template +struct __uninitialized_copy_helper { + static T* uninitialized_copy(T* first, T* last, T* result) { + return __uninitialized_copy(first, last, result); + } +}; + +template +struct __uninitialized_copy_helper +{ + static T* uninitialized_copy(T* first, T* last, T* result) + { + for (; first < last; ++result, ++first) + *result = *first; + return result; + } +}; + +template +inline T* uninitialized_copy(T* first, T* last, T* result) { + return __uninitialized_copy_helper::uninitialized_copy(first, last, result); +} + +} + +#endif + + +#endif /* MSL_MEMORY_H */