From 2a7336959c51704f3a864ad0b3a9b5c13c022034 Mon Sep 17 00:00:00 2001 From: Steven Casper Date: Thu, 20 Mar 2025 18:34:05 -0400 Subject: [PATCH 1/3] xAnimPoolInit matched (thanks Chippy) --- src/SB/Core/x/xAnim.cpp | 60 +++++++++++++++++++++++------------------ 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/SB/Core/x/xAnim.cpp b/src/SB/Core/x/xAnim.cpp index 91125cf53..550fb5976 100644 --- a/src/SB/Core/x/xAnim.cpp +++ b/src/SB/Core/x/xAnim.cpp @@ -1787,57 +1787,65 @@ void xAnimPoolCB(xMemPool* pool, void* data) clone->Pool = pool; } -// WIP +#define ADD_4_BITS(x) (((x) & 1) + (((x) >> 1) & 1) + (((x) >> 2) & 1) + (((x) >> 3) & 1)) void xAnimPoolInit(xMemPool* pool, U32 count, U32 singles, U32 blendFlags, U32 effectMax) { - // unsigned int size; // r22 - // unsigned int i; // r7 - // void* buffer; // r2 effectMax += effectMax & 1; - U32 size = (1 << singles) - 1; + + U32 size = + (effectMax * sizeof(xAnimActiveEffect) + sizeof(xAnimSingle)) * + (ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x0)) + + ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x4)) + + ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0x8)) + + ADD_4_BITS((blendFlags & 0xffff) & ((int)(1 << singles) - 1 >> 0xC)) + singles) + + sizeof(xAnimPlay); + + U32 i; void* buffer = xMemAllocSize(count * size); - xAnimPlay* play; - xAnimSingle* currsingle = (xAnimSingle*)((U32)buffer + 0x20 + singles * sizeof(xAnimSingle)); - xAnimActiveEffect* curract; // r2 + xAnimPlay* play = (xAnimPlay*)buffer; + play->NumSingle = singles; + + xAnimSingle* currsingle; + play->Single = currsingle = (xAnimSingle*)((U32)play + sizeof(xAnimPlay)); + currsingle += singles; - for (U32 i = 0; i < singles; ++i) + for (i = 0; i < singles; ++i) { - if (blendFlags & (1 << (i % 0x40))) + if (blendFlags & (1 << i)) { - ((xAnimSingle*)((U32)buffer + 8))[i].Blend = currsingle; + play->Single[i].Blend = currsingle; currsingle->Blend = NULL; currsingle++; } else { - ((xAnimSingle*)((U32)buffer + 8))[i].Blend = NULL; + play->Single[i].Blend = NULL; } } - for (U32 i = 0; i < *(U16*)((U32)buffer + 4); ++i) + xAnimActiveEffect* curract = (xAnimActiveEffect*)currsingle; + for (i = 0; i < play->NumSingle; ++i) { - xAnimSingle* s2 = &((xAnimSingle*)((U32)buffer + 8))[i]; - if (effectMax != 0) + currsingle = &play->Single[i]; + while (currsingle) { - for (; s2 != NULL; s2 = s2->Blend) + currsingle->ActiveCount = effectMax; + if (effectMax != 0) { - s2->ActiveCount = effectMax; - s2->ActiveList = (xAnimActiveEffect*)currsingle; - ((xAnimActiveEffect*)currsingle) += effectMax; + currsingle->ActiveList = curract; + curract += effectMax; } - } - else - { - for (; s2 != NULL; s2 = s2->Blend) + else { - s2->ActiveCount = 0; - s2->ActiveList = NULL; + currsingle->ActiveList = NULL; } + + currsingle = currsingle->Blend; } } - *(xMemPool**)((U32)buffer + 0x14) = pool; + play->Pool = pool; xMemPoolSetup(pool, buffer, 0, 1, xAnimPoolCB, size, count, count / 2); } From 8b6c7faa6a1cfb2f37d290c1d9868648dcf8d4d0 Mon Sep 17 00:00:00 2001 From: Steven Casper Date: Thu, 20 Mar 2025 23:50:07 -0400 Subject: [PATCH 2/3] xAnim SingleUpdate matched --- .../MSL/MSL_C/MSL_Common/Include/stdio.h | 14 +- src/SB/Core/x/xAnim.cpp | 316 +++++++++++++++++- src/SB/Core/x/xAnim.h | 12 + 3 files changed, 340 insertions(+), 2 deletions(-) diff --git a/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdio.h b/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdio.h index 32578ebbb..5174e1851 100644 --- a/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdio.h +++ b/include/PowerPC_EABI_Support/MSL/MSL_C/MSL_Common/Include/stdio.h @@ -5,11 +5,23 @@ extern "C" { #endif +typedef struct _FILE +{ + U8 pad[0x50]; +} FILE; + +extern FILE __files[4]; + +#define stdin &(__files[0]) +#define stdout &(__files[1]) +#define stderr &(__files[2]) + int sprintf(char* s, const char* format, ...); void printf(const char* format, ...); +int fprintf(FILE* stream, const char* format, ...); #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/src/SB/Core/x/xAnim.cpp b/src/SB/Core/x/xAnim.cpp index 550fb5976..5b71a5ab0 100644 --- a/src/SB/Core/x/xAnim.cpp +++ b/src/SB/Core/x/xAnim.cpp @@ -15,6 +15,7 @@ #include #include +#include static xMemPool sxAnimTempTranPool; @@ -1461,7 +1462,320 @@ void xAnimPlaySetState(xAnimSingle* single, xAnimState* state, F32 startTime) single->BlendFactor = 0.0f; } -void SingleUpdate(xAnimSingle* single, F32 timeDelta); +static void SingleUpdate(xAnimSingle* single, F32 timeDelta) +{ + U32 foundBlendstop = 0; + U32 firstStep = 1; + xAnimTransition* foundTransition = NULL; + xAnimSingle* bl = NULL; + F32 tranDelta = 0.0f; + F32 blendDelta = 0.0f; + F32 singleTime; + if (single->State == NULL) + { + return; + } + + void* object = single->Play->Object; + if (single->LastTime == -1.0f) + { + EffectSingleStart(single); + } + + single->LastTime = single->Time; + singleTime = timeDelta * single->CurrentSpeed + single->Time; + + if (single->Blend != NULL && single->Blend->State != NULL) + { + bl = single->Blend; + if (bl->LastTime == -1.0f) + { + EffectSingleStart(bl); + } + bl->LastTime = bl->Time; + } + + F32 duration = single->State->Data->Duration; + if (single->Sync != NULL) + { + // FIXME: assignment in the loop seems unlikely but assigning at the + // declaration swaps instructions. + F32 timeCmp; + if ((timeCmp = single->Sync->SrcTime) != 0.0f) + { + if (timeCmp > duration) + { + timeCmp = duration; + } + if (single->LastTime <= timeCmp && singleTime >= timeCmp) + { + foundTransition = single->Sync; + tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; + timeDelta = timeDelta - tranDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + } + else + { + timeCmp += duration; + if (single->LastTime <= timeCmp && singleTime >= timeCmp) + { + foundTransition = single->Sync; + tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; + timeDelta = timeDelta - tranDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + } + } + } + else if (bl == NULL) + { + foundTransition = single->Sync; + tranDelta = timeDelta; + timeDelta = 0.0f; + } + } + else + { + if ((single->State->Flags & 0x30) == 0x20) + { + F32 timeCmp = single->State->Default->T->SrcTime; + + if (timeCmp == 0.0f || timeCmp > duration) + { + timeCmp = duration; + } + + if (singleTime >= timeCmp && + ((single->State->Default->T->Flags & 0x4) == 0 || bl == NULL)) + { + xAnimTransitionList* curr = single->State->Default; + // FIXME: this should probably just be a loop + goto start; + loop: + curr = curr->Next; + start: + if (curr != NULL) + { + if (curr->T->Conditional != NULL && + curr->T->Conditional(curr->T, single, object) == 0) + { + goto loop; + } + } + + if (curr == NULL) + { + fprintf(stderr, "State \"%s\" no default conditionals true!\n", + single->State->Name); + curr = single->State->Default; + } + + foundTransition = curr->T; + if (single->LastTime < timeCmp) + { + tranDelta = (singleTime - timeCmp) / single->CurrentSpeed; + timeDelta = timeDelta - tranDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + } + else + { + tranDelta = timeDelta; + timeDelta = 0.0f; + } + } + } + } + + if (single->BlendFactor != 0.0f) + { + F32 recip; + if (single->Tran != NULL) + { + recip = single->Tran->BlendRecip; + } + else + { + recip = single->State->FadeRecip; + } + + if (recip * (single->BlendFactor + timeDelta) > 1.0f) + { + foundBlendstop = 1; + blendDelta = (single->BlendFactor + timeDelta) - (1.0f / recip); + timeDelta = timeDelta - blendDelta; + if (timeDelta < 0.0f) + { + timeDelta = 0.0f; + } + if (blendDelta < 0.0f) + { + blendDelta = 0.01f; + } + } + } + + do + { + if (!firstStep) + { + if (foundBlendstop) + { + single->BlendFactor = 0.0f; + if (bl != NULL) + { + EffectSingleStop(bl); + bl->State = NULL; + bl = NULL; + + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = NULL; + } + else + { + if (single->Tran != NULL) + { + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = NULL; + } + else + { + EffectSingleStop(single); + single->State = NULL; + return; + } + } + timeDelta = blendDelta; + foundBlendstop = FALSE; + } + else + { + if (bl != NULL) + { + EffectSingleStop(bl); + bl->State = NULL; + bl = NULL; + single->BlendFactor = 0.0f; + } + if (foundTransition->BlendRecip == 0.0f || single->Blend == NULL) + { + EffectSingleStop(single); + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = NULL; + } + else + { + bl = single->Blend; + bl->State = single->State; + bl->Time = single->Time; + bl->CurrentSpeed = single->CurrentSpeed; + bl->BilinearLerp[0] = single->BilinearLerp[0]; + bl->BilinearLerp[1] = single->BilinearLerp[1]; + bl->Effect = single->Effect; + bl->LastTime = single->LastTime; + memcpy(bl->ActiveList, single->ActiveList, + single->ActiveCount * sizeof(xAnimTransitionList)); + single->ActiveList->Effect = NULL; + + if (single->Tran != NULL && single->Tran->Flags & 0x2) + { + xMemPoolFree(&sxAnimTempTranPool, single->Tran); + } + single->Tran = foundTransition; + single->BlendFactor = 0.0000001f; + } + + TransitionTimeInit(single, foundTransition); + single->State = foundTransition->Dest; + single->CurrentSpeed = single->State->Speed; + single->BilinearLerp[0] = 0.0f; + single->BilinearLerp[1] = 0.0f; + single->Sync = NULL; + EffectSingleStart(single); + + if (foundTransition->Dest->BeforeEnter != NULL) + { + foundTransition->Dest->BeforeEnter(single->Play, foundTransition->Dest); + } + if (foundTransition->Callback != NULL) + { + foundTransition->Callback(foundTransition, single, single->Play->Object); + } + timeDelta = tranDelta; + foundTransition = NULL; + } + } + + single->Time = timeDelta * single->CurrentSpeed + single->Time; + if (single->BlendFactor != 0.0f) + { + single->BlendFactor += timeDelta; + } + if ((single->State->Flags & 0x30) == 0x10) + { + LoopUpdate(single); + } + else + { + StopUpdate(single); + } + EffectSingleRun(single); + + if (bl != NULL) + { + if ((bl->State->Flags & 0x30) == 0x10) + { + LoopUpdate(bl); + } + else + { + StopUpdate(bl); + } + EffectSingleRun(bl); + } + + firstStep = FALSE; + } while (foundBlendstop || foundTransition != NULL); + + if (single->Tran == NULL && single->BlendFactor == 0.0f) + { + if ((single->State->Flags & 0x30) == 0x30) + { + if (single->State->Flags & 0x200) + { + if (single->Time >= duration) + { + single->BlendFactor = 0.0000001f; + } + } + else if (single->State->FadeRecip * (duration - single->Time) < 1.0f) + { + single->BlendFactor = 0.0000001f; + } + } + } + EffectSingleDuration(single); + if (bl != NULL) + { + EffectSingleDuration(bl); + } +} static void SingleEval(xAnimSingle* single, xVec3* tran, xQuat* quat) { diff --git a/src/SB/Core/x/xAnim.h b/src/SB/Core/x/xAnim.h index 265622c91..6e5d1e45b 100644 --- a/src/SB/Core/x/xAnim.h +++ b/src/SB/Core/x/xAnim.h @@ -20,10 +20,14 @@ struct xAnimFile const char* Name; U32 ID; U32 FileFlags; + + // 0x10 F32 Duration; F32 TimeOffset; U16 BoneCount; U8 NumAnims[2]; + + // 0x20 void** RawData; }; @@ -53,18 +57,26 @@ struct xAnimState const char* Name; U32 ID; U32 Flags; + + // 0x10 U32 UserFlags; F32 Speed; xAnimFile* Data; xAnimEffect* Effects; + + // 0x20 xAnimTransitionList* Default; xAnimTransitionList* List; F32* BoneBlend; F32* TimeSnap; + + // 0x30 F32 FadeRecip; U16* FadeOffset; void* CallbackData; xAnimMultiFile* MultiFile; + + // 0x40 xAnimStateBeforeEnterCallback BeforeEnter; xAnimStateCallback StateCallback; xAnimStateBeforeAnimMatricesCallback BeforeAnimMatrices; From bf1e32646232a799a05a98274390193f6ae7f0c7 Mon Sep 17 00:00:00 2001 From: Steven Casper Date: Fri, 21 Mar 2025 01:25:13 -0400 Subject: [PATCH 3/3] xAnim 97% --- src/SB/Core/x/xAnim.cpp | 28 ++++++++++------------------ src/SB/Core/x/xString.h | 2 +- 2 files changed, 11 insertions(+), 19 deletions(-) diff --git a/src/SB/Core/x/xAnim.cpp b/src/SB/Core/x/xAnim.cpp index 5b71a5ab0..18a2f2ce3 100644 --- a/src/SB/Core/x/xAnim.cpp +++ b/src/SB/Core/x/xAnim.cpp @@ -375,7 +375,7 @@ float std::atan2f(float y, float x) float CalcRecipBlendMax(U16* arg0) { - float ret = 0.0f; + float max = 0.0f; while (arg0[0] != 0xFFFF) { float f3; @@ -385,22 +385,22 @@ float CalcRecipBlendMax(U16* arg0) } else { - f3 = 1.0f / (0.001f * arg0[1]); + f3 = 1.0f / (0.0009765625f * arg0[1]); } f3 = 0.001f * arg0[0] + f3; - if (f3 > ret) + if (f3 > max) { - ret = f3; + max = f3; } arg0 += 2; } - if (ret == 0.0f) + if (max == 0.0f) { return 0.0f; } - return 1.0f / ret; + return 1.0f / max; } static U32 StateHasTransition(xAnimState* state, xAnimTransition* tran) @@ -514,7 +514,7 @@ xAnimFile* xAnimFileNewBilinear(void** rawData, const char* name, U32 flags, xAn } afile->RawData = (void**)&afile[1]; - for (S32 i = 0; i < numX * numY; ++i) + for (S32 i = 0; i < (S32)numX * (S32)numY; ++i) { afile->RawData[i] = rawData[i]; } @@ -1554,18 +1554,10 @@ static void SingleUpdate(xAnimSingle* single, F32 timeDelta) ((single->State->Default->T->Flags & 0x4) == 0 || bl == NULL)) { xAnimTransitionList* curr = single->State->Default; - // FIXME: this should probably just be a loop - goto start; - loop: - curr = curr->Next; - start: - if (curr != NULL) + while (curr != NULL && curr->T->Conditional != NULL && + curr->T->Conditional(curr->T, single, object) == 0) { - if (curr->T->Conditional != NULL && - curr->T->Conditional(curr->T, single, object) == 0) - { - goto loop; - } + curr = curr->Next; } if (curr == NULL) diff --git a/src/SB/Core/x/xString.h b/src/SB/Core/x/xString.h index 94aecb590..8ceaf9250 100644 --- a/src/SB/Core/x/xString.h +++ b/src/SB/Core/x/xString.h @@ -21,7 +21,7 @@ U32 xStrHashCat(U32 prefix, const char* str); char* xStrupr(char* string); S32 xStricmp(const char* string1, const char* string2); char* xStrTok(char* string, const char* control, char** nextoken); -char* xStrTokBuffer(const char* string, char* control, void* buffer); +char* xStrTokBuffer(const char* string, const char* control, void* buffer); S32 xStrParseFloatList(F32* dest, const char* strbuf, S32 max); S32 imemcmp(void const* d1, void const* d2, size_t size);