#include #include "constants.h" #include "game/prop.h" #include "game/game_1531a0.h" #include "game/bg.h" #include "bss.h" #include "lib/dma.h" #include "lib/memp.h" #include "lib/mtx.h" #include "lib/anim.h" #include "lib/lib_2f490.h" #include "lib/libc/ll.h" #include "data.h" #include "types.h" u8 *var8009a870; u8 **var8009a874; s16 *var8009a878; s16 *var8009a87c; u8 *var8009a880; u8 *var8009a884; u8 **var8009a888; s16 *var8009a88c; s32 *var8009a890; s16 var8009a894; struct animsummary *var8009a898; u32 var8005f000 = 0; s32 var8005f004 = 0; s16 g_NumAnimations = 0; struct animsummary *g_Anims = NULL; u8 *var8005f010 = NULL; s16 *var8005f014 = NULL; s32 var8005f018 = 176; s32 var8005f01c = 608; bool g_AnimHostEnabled = false; u8 *g_AnimHostSegment = NULL; extern u8 _animationsTableRomStart; extern u8 _animationsTableRomEnd; void animsInit(void) { s32 i; u32 *ptr; u32 tablelen = ALIGN64(&_animationsTableRomEnd - &_animationsTableRomStart); ptr = mempAlloc(tablelen, MEMPOOL_PERMANENT); dmaExec(ptr, (s32)&_animationsTableRomStart, tablelen); g_NumAnimations = var8009a894 = ptr[0]; g_Anims = var8009a898 = (struct animsummary *)&ptr[1]; var8005f01c = 1; var8005f018 = 1; for (i = 0; i < g_NumAnimations; i++) { if (g_Anims[i].headerlen > var8005f01c) { var8005f01c = g_Anims[i].headerlen; } if (g_Anims[i].bytesperframe > var8005f018) { var8005f018 = g_Anims[i].bytesperframe; } } var8005f01c = ALIGN16(var8005f01c + 34); var8005f018 = ALIGN16(var8005f018 + 34); var8005f010 = mempAlloc(ALIGN64(g_NumAnimations), MEMPOOL_PERMANENT); var8005f014 = mempAlloc(ALIGN64(g_NumAnimations * 2), MEMPOOL_PERMANENT); var8009a870 = mempAlloc(ALIGN64(var8005f018 * 0x20), MEMPOOL_PERMANENT); var8009a874 = mempAlloc(0x80, MEMPOOL_PERMANENT); var8009a878 = mempAlloc(0x40, MEMPOOL_PERMANENT); var8009a87c = mempAlloc(0x40, MEMPOOL_PERMANENT); var8009a880 = mempAlloc(0x40, MEMPOOL_PERMANENT); var8009a884 = mempAlloc(ALIGN64(var8005f01c * 40), MEMPOOL_PERMANENT); var8009a888 = mempAlloc(0xc0, MEMPOOL_PERMANENT); var8009a88c = mempAlloc(0x80, MEMPOOL_PERMANENT); var8009a890 = mempAlloc(0xc0, MEMPOOL_PERMANENT); animsInitTables(); g_AnimHostSegment = NULL; g_AnimHostEnabled = false; } void animsInitTables(void) { s32 i; for (i = 0; i < g_NumAnimations; i++) { var8005f010[i] = 0xff; var8005f014[i] = 0; } for (i = 0; i < 32; i++) { var8009a878[i] = 0; var8009a87c[i] = 0; var8009a880[i] = 0; } for (i = 0; i < 40; i++) { var8009a88c[i] = 0; var8009a890[i] = -2; } } void animsReset(void) { g_NumAnimations = var8009a894; g_Anims = var8009a898; g_AnimHostEnabled = false; } s32 animGetNumFrames(s16 animnum) { return g_Anims[animnum].numframes; } bool animHasFrames(s16 animnum) { return animnum < g_NumAnimations && g_Anims[animnum].numframes > 0; } s32 animGetNumAnimations(void) { return g_NumAnimations; } extern u8 _animationsSegmentRomStart; u8 *animDma(u8 *dst, u32 segoffset, u32 len) { if (g_AnimHostEnabled) { bcopy(&g_AnimHostSegment[segoffset], dst, len); return dst; } return dmaExecWithAutoAlign(dst, (u32)&_animationsSegmentRomStart + segoffset, len); } s32 anim0002384c(s16 animnum, s32 frame) { u8 *ptr = (u8 *)(var8009a888[var8005f010[animnum]] + g_Anims[animnum].headerlen - 2); s32 result = frame; while (true) { s16 value1 = ptr[0] << 8 | ptr[1]; s16 value2; if (value1 < 0) { break; } value2 = ptr[-2] << 8 | ptr[-1]; ptr -= 4; if (value1 <= frame) { if (value2 < frame) { result = result - value2 + value1 - 1; } else { result = -1; break; } } } return result; } bool anim00023908(s16 animnum, s32 frame, s32 *frameptr) { u8 *ptr = (u8 *)(var8009a888[var8005f010[animnum]] + g_Anims[animnum].headerlen - 2); s32 result = frame; bool ret = true; while (true) { s16 value1 = ptr[0] << 8 | ptr[1]; if (value1 >= 0) { s16 value2 = ptr[-2] << 8 | ptr[-1]; ptr -= 4; if (value1 <= frame) { if (value2 < frame) { result = result - value2 + value1 - 1; continue; } result = result - frame + value1; ret = false; break; } } else { break; } } *frameptr = result; return ret; } bool anim000239e0(s16 animnum, s32 frame) { u8 *ptr = (u8 *)(var8009a888[var8005f010[animnum]] + g_Anims[animnum].headerlen - 2); if (g_Anims[animnum].flags & ANIMFLAG_04) { while (true) { s16 value1 = ptr[0] << 8 | ptr[1]; if (value1 < 0) { break; } ptr -= 4; } ptr -= 2; } while (true) { s16 value2 = ptr[0] << 8 | ptr[1]; if (value2 < 0) { break; } if (value2 == frame) { return true; } ptr -= 2; } return false; } u8 anim00023ab0(s16 animnum, s32 framenum) { s32 index = -1; s32 i; s32 offset; s32 stack; s32 sp2c = framenum; for (i = 0; i < 32; i++) { if (var8009a878[i] == animnum && var8009a87c[i] == sp2c) { index = i; break; } } if (index >= 0) { var8009a880[index] = 1; } else { index = var8005f000; while (var8009a880[index]) { index = (index + 1) % 32; } if (g_Anims[animnum].flags & ANIMFLAG_04) { anim00023908(animnum, framenum, &sp2c); } if (g_Anims[animnum].bytesperframe) { offset = g_Anims[animnum].bytesperframe * sp2c + (g_Anims[animnum].data + g_Anims[animnum].headerlen); var8009a874[index] = animDma(&var8009a870[index * var8005f018], offset, g_Anims[animnum].bytesperframe); } else { var8009a874[index] = &var8009a870[index * var8005f018]; } var8009a878[index] = animnum; var8009a87c[index] = framenum; var8009a880[index] = 1; var8005f000 = (index + 1) % 32; } return index; } void anim00023d0c(void) { s32 i; for (i = 0; i < 32; i++) { var8009a880[i] = 0; } } void anim00023d38(s16 animnum) { s32 i; if (var8005f010[animnum] != 0xff) { var8009a890[var8005f010[animnum]] = g_Vars.thisframestart240; var8005f004 = (var8005f010[animnum] + 1) % 40; } else { s32 tmp; s32 bestindex = var8005f004; s32 stack; for (i = 0; i < 40; i++) { if (var8009a890[i] < var8009a890[bestindex]) { bestindex = i; } } if (var8009a890[bestindex]); if (&g_Vars && &g_Vars); if (var8009a88c[bestindex]) { var8005f010[var8009a88c[bestindex]] = 0xff; } tmp = g_Anims[animnum].headerlen; var8009a888[bestindex] = animDma(&var8009a884[bestindex * var8005f01c], g_Anims[animnum].data, tmp); var8005f010[animnum] = bestindex; var8009a88c[bestindex] = animnum; var8009a890[bestindex] = g_Vars.thisframestart240; var8005f004 = (bestindex + 1) % 40; } } #if MATCHING GLOBAL_ASM( glabel anim00023f50 /* 23f50: 30cf0007 */ andi $t7,$a2,0x7 /* 23f54: 24180008 */ addiu $t8,$zero,0x8 /* 23f58: 030f4023 */ subu $t0,$t8,$t7 /* 23f5c: 30a900ff */ andi $t1,$a1,0xff /* 23f60: 311900ff */ andi $t9,$t0,0xff /* 23f64: 000610c2 */ srl $v0,$a2,0x3 /* 23f68: 0139082a */ slt $at,$t1,$t9 /* 23f6c: afa50004 */ sw $a1,0x4($sp) /* 23f70: 00001825 */ or $v1,$zero,$zero /* 23f74: 00822021 */ addu $a0,$a0,$v0 /* 23f78: 1420000e */ bnez $at,.L00023fb4 /* 23f7c: 310700ff */ andi $a3,$t0,0xff .L00023f80: /* 23f80: 908b0000 */ lbu $t3,0x0($a0) /* 23f84: 240c0001 */ addiu $t4,$zero,0x1 /* 23f88: 01272823 */ subu $a1,$t1,$a3 /* 23f8c: 00ec6804 */ sllv $t5,$t4,$a3 /* 23f90: 30a900ff */ andi $t1,$a1,0xff /* 23f94: 25aeffff */ addiu $t6,$t5,-1 /* 23f98: 016e7824 */ and $t7,$t3,$t6 /* 23f9c: 012fc004 */ sllv $t8,$t7,$t1 /* 23fa0: 29210008 */ slti $at,$t1,0x8 /* 23fa4: 00781825 */ or $v1,$v1,$t8 /* 23fa8: 24840001 */ addiu $a0,$a0,0x1 /* 23fac: 1020fff4 */ beqz $at,.L00023f80 /* 23fb0: 24070008 */ addiu $a3,$zero,0x8 .L00023fb4: /* 23fb4: 19200008 */ blez $t1,.L00023fd8 /* 23fb8: 00e95023 */ subu $t2,$a3,$t1 /* 23fbc: 90990000 */ lbu $t9,0x0($a0) /* 23fc0: 240d0001 */ addiu $t5,$zero,0x1 /* 23fc4: 012d5804 */ sllv $t3,$t5,$t1 /* 23fc8: 256effff */ addiu $t6,$t3,-1 /* 23fcc: 01596007 */ srav $t4,$t9,$t2 /* 23fd0: 018e7824 */ and $t7,$t4,$t6 /* 23fd4: 006f1825 */ or $v1,$v1,$t7 .L00023fd8: /* 23fd8: 03e00008 */ jr $ra /* 23fdc: 00601025 */ or $v0,$v1,$zero ); #else // Mismatch: regalloc s32 anim00023f50(u8 *arg0, u8 arg1, u32 arg2) { u32 result = 0; u8 numbits; u32 tmp; arg0 += arg2 / 8; numbits = 8 - (arg2 % 8); while (arg1 >= numbits) { arg1 -= numbits; result |= (*arg0 & ((1 << numbits) - 1)) << arg1; arg0++; numbits = 8; } if (arg1 > 0) { result |= (*arg0 >> (numbits - arg1)) & ((1 << arg1) - 1); } if (arg2 / 8); return result; } #endif s32 anim00023fe0(u8 *arg0, u8 arg1, s32 arg2) { u16 result = anim00023f50(arg0, arg1, arg2); if (arg1 < 16 && (result & (1 << (arg1 - 1)))) { result |= ((1 << (16 - arg1)) - 1) << arg1; } return result; } void anim00024050(s32 arg0, bool flip, struct skeleton *skel, s16 animnum, u8 arg4, struct coord *arg5, struct coord *arg6, struct coord *arg7) { s32 i; u16 sp5c[3]; u8 sp5b; u8 *sp54 = var8009a874[arg4]; u8 bitsperentry; u8 *ptr; u8 *end; s32 sum; u32 stack; if (flip) { arg0 = skel->things[arg0][1]; } bitsperentry = g_Anims[animnum].initialposbitsperentry; ptr = var8009a888[var8005f010[animnum]]; sum = 0; end = ptr + g_Anims[animnum].headerlen; for (i = 0; i < arg0 && ptr < end; i++) { u8 flags = *ptr; ptr++; if (flags & 0x08) { sum += ptr[2] + ptr[5] + ptr[8] + ptr[11]; ptr += 12; } else if (flags & 0x02) { sum += ptr[2] + ptr[5] + ptr[8]; ptr += 9; } else if (flags & 0x20) { sum += ptr[0] + ptr[5] + ptr[10]; ptr += 15; } if (flags & 0x01) { sum += ptr[2] + ptr[5] + ptr[8]; ptr += 9; } else if (flags & 0x10) { sum += 96; } if (flags & 0x40) { sum += ptr[0]; ptr += 5; } if (flags & 0x80) { sum += 0x60; } } if (ptr < end) { u8 flags = *ptr; ptr++; if (flags & 0x02) { sp5b = ptr[2]; arg6->x = (s16) (anim00023fe0(sp54, sp5b, sum) + (ptr[0] << 8) + ptr[1]); sum += sp5b; sp5b = ptr[5]; arg6->y = (s16) (anim00023fe0(sp54, sp5b, sum) + (ptr[3] << 8) + ptr[4]); sum += sp5b; sp5b = ptr[8]; arg6->z = (s16) (anim00023fe0(sp54, sp5b, sum) + (ptr[6] << 8) + ptr[7]); sum += sp5b; ptr += 9; } else if (flags & 0x20) { sp5b = ptr[0]; arg6->x = (anim00023f50(sp54, sp5b, sum) + ((ptr[1] << 24) + (ptr[2] << 16) + (ptr[3] << 8) + ptr[4])) * 0.001f; sum += sp5b; sp5b = ptr[5]; arg6->y = (anim00023f50(sp54, sp5b, sum) + ((ptr[6] << 24) + (ptr[7] << 16) + (ptr[8] << 8) + ptr[9])) * 0.001f; sum += sp5b; sp5b = ptr[10]; arg6->z = (anim00023f50(sp54, sp5b, sum) + ((ptr[11] << 24) + (ptr[12] << 16) + (ptr[13] << 8) + ptr[14])) * 0.001f; sum += sp5b; ptr += 15; } else { if (flags & 0x08) { sum += ptr[2] + ptr[5] + ptr[8] + ptr[11]; ptr += 12; } arg6->x = arg6->y = arg6->z = 0.0f; } if (flags & 0x01) { sp5b = ptr[2]; sp5c[0] = anim00023f50(sp54, sp5b, sum); sp5c[0] += (ptr[0] << 8) + ptr[1]; sp5c[0] <<= 16 - bitsperentry; sum += sp5b; sp5b = ptr[5]; sp5c[1] = anim00023f50(sp54, sp5b, sum); sp5c[1] += (ptr[3] << 8) + ptr[4]; sp5c[1] <<= 16 - bitsperentry; sum += sp5b; sp5b = ptr[8]; sp5c[2] = anim00023f50(sp54, sp5b, sum); sp5c[2] += (ptr[6] << 8) + ptr[7]; sp5c[2] <<= 16 - bitsperentry; sum += sp5b; arg5->x = sp5c[0] * M_BADTAU / 65536.0f; if (flip) { if (sp5c[1] != 0) { arg5->y = (0x10000 - sp5c[1]) * M_BADTAU / 65536.0f; } else { arg5->y = 0.0f; } if (sp5c[2] != 0) { arg5->z = (0x10000 - sp5c[2]) * M_BADTAU / 65536.0f; } else { arg5->z = 0.0f; } } else { arg5->y = sp5c[1] * M_BADTAU / 65536.0f; arg5->z = sp5c[2] * M_BADTAU / 65536.0f; } } else if (flags & 0x10) { s32 sp38; sp38 = anim00023f50(sp54, 32, sum); arg5->x = *(f32 *)&sp38; sum += 32; sp38 = anim00023f50(sp54, 32, sum); arg5->y = *(f32 *)&sp38; sum += 32; sp38 = anim00023f50(sp54, 32, sum); arg5->z = *(f32 *)&sp38; sum += 32; if (flip) { if (arg5->y != 0.0f) { arg5->y = M_BADTAU - arg5->y; } if (arg5->z != 0.0f) { arg5->z = M_BADTAU - arg5->z; } } } else { arg5->x = arg5->y = arg5->z = 0.0f; } if (flags & 0x80) { s32 sp34; sp34 = anim00023f50(sp54, 32, sum); arg7->x = *(f32 *)&sp34; sum += 32; sp34 = anim00023f50(sp54, 32, sum); arg7->y = *(f32 *)&sp34; sum += 32; sp34 = anim00023f50(sp54, 32, sum); arg7->z = *(f32 *)&sp34; } else { arg7->x = arg7->y = arg7->z = 1.0f; } return; } arg5->x = arg5->y = arg5->z = 0.0f; arg6->x = arg6->y = arg6->z = 0.0f; arg7->x = arg7->y = arg7->z = 1.0f; } u16 anim0002485c(s32 arg0, bool arg1, struct skeleton *skel, s16 animnum, s32 loopframe, s16 *arg5, bool arg6) { u16 result = 0; s32 sum; u8 sp2f; u8 index; u8 *sp28; u8 *ptr; s32 i; if (arg6) { arg5[0] = 0; arg5[1] = 0; arg5[2] = var8005f014[animnum]; } else { anim00023d38(animnum); index = anim00023ab0(animnum, loopframe); anim00023d0c(); sp28 = var8009a874[index]; if (arg1) { arg0 = skel->things[arg0][1]; } // This is iterating the header information in the animation's data sum = 0; ptr = var8009a888[var8005f010[animnum]]; for (i = 0; i < arg0; i++) { u8 flags = *ptr; ptr++; if (flags & 0x08) { sum += ptr[2] + ptr[5] + ptr[8] + ptr[11]; ptr += 12; } else if (flags & 0x02) { sum += ptr[2] + ptr[5] + ptr[8]; ptr += 9; } else if (flags & 0x20) { sum += ptr[0] + ptr[5] + ptr[10]; ptr += 15; } if (flags & 0x01) { sum += ptr[2] + ptr[5] + ptr[8]; ptr += 9; } else if (flags & 0x10) { sum += 96; } if (flags & 0x40) { sum += *ptr; ptr += 5; } if (flags & 0x80) { sum += 96; } } sp2f = ptr[3]; arg5[0] = anim00023fe0(sp28, sp2f, sum) + ptr[1] * 256 + ptr[2]; sum += sp2f; sp2f = ptr[6]; arg5[1] = anim00023fe0(sp28, sp2f, sum) + ptr[4] * 256 + ptr[5]; sum += sp2f; sp2f = ptr[9]; arg5[2] = anim00023fe0(sp28, sp2f, sum) + ptr[7] * 256 + ptr[8]; sum += sp2f; sp2f = ptr[12]; result = anim00023fe0(sp28, sp2f, sum) + ptr[10] * 256 + ptr[11]; if (arg1) { arg5[0] = -arg5[0]; if (result != 0) { result = 0x10000 - result; } } } return result; } f32 anim00024b64(u32 arg0, u32 arg1, struct skeleton *arg2, s16 animnum, u32 arg4, struct coord *coord, u32 arg6) { s16 sp30[3]; f32 value = anim0002485c(arg0, arg1, arg2, animnum, arg4, sp30, arg6); coord->x = sp30[0]; coord->y = sp30[1]; coord->z = sp30[2]; return value * M_BADTAU / 65536.0f; } f32 anim00024c14(s32 arg0, s16 animnum, u8 arg2) { u32 stack[2]; u8 *sp24 = var8009a874[arg2]; u8 *ptr = var8009a888[var8005f010[animnum]]; f32 result = 0; s32 total = 0; s32 i; u8 *end = ptr + g_Anims[animnum].headerlen; for (i = 0; i < arg0 && ptr < end; i++) { u8 flags = ptr[0]; ptr++; if (flags & ANIMHEADERFLAG_08) { total += ptr[2] + ptr[5] + ptr[8] + ptr[11]; ptr += 12; } else if (flags & ANIMHEADERFLAG_02) { total += ptr[2] + ptr[5] + ptr[8]; ptr += 9; } else if (flags & ANIMHEADERFLAG_20) { total += ptr[0] + ptr[5] + ptr[10]; ptr += 15; } if (flags & ANIMHEADERFLAG_01) { total += ptr[2] + ptr[5] + ptr[8]; ptr += 9; } else if (flags & ANIMHEADERFLAG_10) { total += 0x60; } if (flags & ANIMHEADERFLAG_40) { total += ptr[0]; ptr += 5; } if (flags & ANIMHEADERFLAG_80) { total += 0x60; } } if (ptr < end) { u8 flags = ptr[0]; ptr++; if (flags & ANIMHEADERFLAG_40) { total = anim00023f50(sp24, ptr[0], total); result = (total + ptr[1] * 0x1000000 + ptr[2] * 0x10000 + ptr[3] * 0x100 + ptr[4]) * 0.001f; } } return result; }