diff --git a/data/file_list.yml b/data/file_list.yml index cfd7bcd54b..7645be11f7 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -288853,37 +288853,37 @@ Project/Anim/AnimInfo.o: label: - _ZN2al11AnimResInfoC1Ev - _ZN2al11AnimResInfoC2Ev - status: NotDecompiled + status: Matching - offset: 0xa3b85c size: 12 label: _ZNK2al11AnimResInfo11getFrameMaxEv - status: NotDecompiled + status: Matching - offset: 0xa3b868 size: 8 label: _ZNK2al11AnimResInfo6isLoopEv - status: NotDecompiled + status: Matching - offset: 0xa3b870 size: 116 label: - _ZN2al13AnimInfoTableC1Ei - _ZN2al13AnimInfoTableC2Ei - status: NotDecompiled + status: Matching - offset: 0xa3b8e4 size: 116 label: _ZN2al13AnimInfoTable3addEPKcPvfb - status: NotDecompiled + status: Matching - offset: 0xa3b958 size: 224 label: _ZNK2al13AnimInfoTable12findAnimInfoEPKc - status: NotDecompiled + status: Matching - offset: 0xa3ba38 size: 224 label: _ZNK2al13AnimInfoTable15tryFindAnimInfoEPKc - status: NotDecompiled + status: NonMatchingMajor - offset: 0xa3bb18 size: 564 label: _ZN2al13AnimInfoTable4sortEv - status: NotDecompiled + status: Matching Project/Anim/AnimPlayerSimple.o: '.text': - offset: 0xa3bd4c diff --git a/lib/al/Project/Action/InitResourceDataActionAnim.cpp b/lib/al/Project/Action/InitResourceDataActionAnim.cpp index 8b84bfcb6e..5067b87dfc 100644 --- a/lib/al/Project/Action/InitResourceDataActionAnim.cpp +++ b/lib/al/Project/Action/InitResourceDataActionAnim.cpp @@ -123,17 +123,16 @@ const al::AnimInfoTable* createAnimInfoTableIfNeed(const al::AnimInfoTable* tabl if (table1 == table2 || !table2) return table1; - al::AnimInfoTable* newTable = - new al::AnimInfoTable(table1->getInfoCount() + table2->getInfoCount()); + al::AnimInfoTable* newTable = new al::AnimInfoTable(table1->getSize() + table2->getSize()); - for (s32 i = 0; i < table1->getInfoCount(); i++) { - const al::AnimResInfo& entry = table1->getResInfo(i); - newTable->add(entry.name, entry.resMaterialAnim, entry.frameMax, entry.isLoop); + for (s32 i = 0; i < table1->getSize(); i++) { + const al::AnimResInfo& entry = table1->getAnimInfo(i); + newTable->add(entry.name, entry.buffer, entry.frameMax, entry.isLooping); } - for (s32 i = 0; i < table2->getInfoCount(); i++) { - const al::AnimResInfo& entry = table2->getResInfo(i); - newTable->add(entry.name, entry.resMaterialAnim, entry.frameMax, entry.isLoop); + for (s32 i = 0; i < table2->getSize(); i++) { + const al::AnimResInfo& entry = table2->getAnimInfo(i); + newTable->add(entry.name, entry.buffer, entry.frameMax, entry.isLooping); } newTable->sort(); diff --git a/lib/al/Project/Anim/AnimInfo.cpp b/lib/al/Project/Anim/AnimInfo.cpp new file mode 100644 index 0000000000..8c7ce93a0d --- /dev/null +++ b/lib/al/Project/Anim/AnimInfo.cpp @@ -0,0 +1,121 @@ +#include "Project/Anim/AnimInfo.h" + +#include "Library/Base/StringUtil.h" + +namespace al { + +AnimResInfo::AnimResInfo() = default; + +s32 AnimResInfo::getFrameMax() const { + return static_cast(frameMax); +} + +bool AnimResInfo::isLoop() const { + return isLooping; +} + +AnimInfoTable::AnimInfoTable(s32 capacity) { + mInfoEntries = new AnimResInfo[capacity]; +} + +void AnimInfoTable::add(const char* name, void* buffer, f32 frameMax, bool isLoop) { + // BUG: Is sorted flag is not cleared and no bounds check + AnimResInfo* info = &mInfoEntries[mSize]; + info->name = createStringIfInStack(name); + info->buffer = buffer; + info->frameMax = frameMax; + info->isLooping = isLoop; + mSize++; +} + +AnimResInfo* AnimInfoTable::findAnimInfo(const char* name) const { + if (mIsSorted) { + s32 low = 0; + s32 high = mSize; + while (low < high) { + s32 mid = (high + low - 1) >> 1; + AnimResInfo* info = &mInfoEntries[mid]; + s32 cmp = strcmp(info->name, name); + + if (cmp > 0) { + high = mid; + continue; + } + + if (cmp == 0) + return info; + + low = mid + 1; + } + return nullptr; + } + + for (s32 i = 0; i < mSize; i++) { + AnimResInfo* info = &mInfoEntries[i]; + if (isEqualString(info->name, name)) + return info; + } + return nullptr; +} + +// NON-MATCHING: Different register somehow https://decomp.me/scratch/ZxdNk +AnimResInfo* AnimInfoTable::tryFindAnimInfo(const char* name) const { + return findAnimInfo(name); +} + +inline void heapify(AnimResInfo* entries, s32 n, const AnimResInfo& temp, s32 parent) { + s32 child = parent * 2; + while (child <= n) { + if (child < n && strcmp(entries[child - 1].name, entries[child].name) < 0) + child++; + + if (strcmp(temp.name, entries[child - 1].name) >= 0) + break; + + entries[parent - 1] = entries[child - 1]; + parent = child; + child = parent * 2; + } + entries[parent - 1] = temp; +} + +void AnimInfoTable::sort() { + s32 n = mSize; + AnimResInfo* entries = mInfoEntries; + + if (n < 2 || !entries) { + mIsSorted = true; + return; + } + + AnimResInfo temp; + + for (s32 i = n / 2; i >= 1; i--) { + temp = entries[i - 1]; + heapify(entries, n, temp, i); + } + + // TODO: Figure out how to apply heapify here as well + for (s32 i = n; i >= 2; i--) { + temp = entries[i - 1]; + entries[i - 1] = entries[0]; + s32 parent = 1; + s32 child = parent * 2; + while (child < i) { + if (child < i - 1 && strcmp(entries[child - 1].name, entries[child].name) < 0) + child++; + + if (strcmp(temp.name, entries[child - 1].name) >= 0) + break; + + entries[parent - 1] = entries[child - 1]; + parent = child; + child = parent * 2; + } + entries[parent - 1] = temp; + } + + mIsSorted = true; +} + +} // namespace al diff --git a/lib/al/Project/Anim/AnimInfo.h b/lib/al/Project/Anim/AnimInfo.h index 4c5a67d81c..b60b4f66f9 100644 --- a/lib/al/Project/Anim/AnimInfo.h +++ b/lib/al/Project/Anim/AnimInfo.h @@ -3,30 +3,39 @@ #include namespace al { + struct AnimResInfo { - const char* name; - void* resMaterialAnim; - f32 frameMax; - bool isLoop; + AnimResInfo(); + + s32 getFrameMax() const; + bool isLoop() const; + + const char* name = nullptr; + void* buffer = nullptr; + f32 frameMax = 0.0f; + bool isLooping = false; }; +static_assert(sizeof(AnimResInfo) == 0x18); + class AnimInfoTable { public: - AnimInfoTable(u32); - - const AnimResInfo& findAnimInfo(const char* name) const; - bool tryFindAnimInfo(const char* name) const; - - void add(const char* name, void*, f32 frameMax, bool isLoop); + AnimInfoTable(s32 capacity); + void add(const char* name, void* buffer, f32 frameMax, bool isLoop); + AnimResInfo* findAnimInfo(const char* name) const; + AnimResInfo* tryFindAnimInfo(const char* name) const; void sort(); - s32 getInfoCount() const { return mInfoCount; } + s32 getSize() const { return mSize; } - const AnimResInfo& getResInfo(s32 index) const { return mResInfos[index]; } + const AnimResInfo& getAnimInfo(s32 index) const { return mInfoEntries[index]; } private: - s32 mInfoCount; - AnimResInfo* mResInfos; - bool mIsSorted; + s32 mSize = 0; + AnimResInfo* mInfoEntries = nullptr; + bool mIsSorted = false; }; + +static_assert(sizeof(AnimInfoTable) == 0x18); + } // namespace al