diff --git a/src/game/bondheadreset.c b/src/game/bondheadreset.c index 1b2a4ff1a..b313ec01f 100644 --- a/src/game/bondheadreset.c +++ b/src/game/bondheadreset.c @@ -97,7 +97,7 @@ void bheadReset(void) struct modelrenderdata renderdata = {NULL, 1, 3}; Mtxf sp48; - modelSetAnimation(&g_Vars.currentplayer->model, 1, 0, 0, 0.5f, 0); + modelSetAnimation(&g_Vars.currentplayer->model, ANIM_TWO_GUN_HOLD, 0, 0, 0.5f, 0); modelUpdateInfo(&g_Vars.currentplayer->model); mtx4LoadIdentity(&sp48); diff --git a/src/include/data.h b/src/include/data.h index bb17addd8..96bed54ca 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -42,10 +42,6 @@ extern bool var8005eedc; extern f32 var8005ef10[2]; extern s32 g_NumGlobalAilists; extern s32 g_NumLvAilists; -extern u32 var8005ef40; -extern u32 var8005ef5c; -extern u32 var8005ef7c; -extern u32 var8005ef90; extern bool g_ModelDistanceDisabled; extern f32 g_ModelDistanceScale; extern bool var8005efbc; diff --git a/src/include/lib/model.h b/src/include/lib/model.h index 777eebbaf..363abfb5f 100644 --- a/src/include/lib/model.h +++ b/src/include/lib/model.h @@ -8,7 +8,7 @@ extern bool (*var8005efc4)(struct model *model, struct modelnode *node); extern struct gfxvtx *(*g_ModelVtxAllocatorFunc)(s32 numvertices); extern void (*g_ModelJointPositionedFunc)(s32 mtxindex, Mtxf *mtx); -bool model00018680(struct modelrenderdata *renderdata, struct model *model); +bool modelasm00018680(struct modelrenderdata *renderdata, struct model *model); void modelSetDistanceScale(f32 value); void modelSetVtxAllocatorFunc(struct gfxvtx *(*fn)(s32 numvertices)); s32 modelFindNodeMtxIndex(struct modelnode *node, s32 arg1); diff --git a/src/lib/model.c b/src/lib/model.c index 34213a12c..ee848dcef 100644 --- a/src/lib/model.c +++ b/src/lib/model.c @@ -1555,11 +1555,11 @@ void modelSetMatrices(struct modelrenderdata *renderdata, struct model *model) renderdata->unk10 += model->definition->nummatrices; #if VERSION >= VERSION_PAL_BETA - if (var8005efb0_2 || !model00018680(renderdata, model)) { + if (var8005efb0_2 || !modelasm00018680(renderdata, model)) { modelUpdateMatrices(renderdata, model); } #else - if (!model00018680(renderdata, model)) { + if (!modelasm00018680(renderdata, model)) { modelUpdateMatrices(renderdata, model); } #endif diff --git a/src/lib/modelasm.s b/src/lib/modelasm.s index 8aa7ddbd6..9cab337fb 100644 --- a/src/lib/modelasm.s +++ b/src/lib/modelasm.s @@ -15,23 +15,23 @@ glabel var8005ef40 .word 0x00000000 glabel var8005ef5c -.word model00018680+0xef4 -.word model00018680+0xa3c -.word model00018680+0x3a8 -.word model00018680+0x990 -.word model00018680+0xecc -.word model00018680+0xed4 -.word model00018680+0xe60 -.word model00018680+0xe24 +.word modelasm00018680+0xef4 +.word modelasm00018680+0xa3c +.word modelasm00018680+0x3a8 +.word modelasm00018680+0x990 +.word modelasm00018680+0xecc +.word modelasm00018680+0xed4 +.word modelasm00018680+0xe60 +.word modelasm00018680+0xe24 glabel var8005ef7c .word 0x00000000 glabel var8005ef80 -.word model00019be0+0x84 -.word model00019be0+0x90 -.word model00019be0+0xa8 -.word model00019be0+0xcc +.word modelasmReadFrameData+0x84 +.word modelasmReadFrameData+0x90 +.word modelasmReadFrameData+0xa8 +.word modelasmReadFrameData+0xcc glabel var8005ef90 .word 0xff08ffff @@ -121,7 +121,7 @@ glabel var70054270 .text -glabel model00018680 +glabel modelasm00018680 addiu $sp, $sp, -2048 sw $s0, 0x780($sp) sw $s1, 0x784($sp) @@ -194,7 +194,7 @@ glabel model00018680 sll $t6, $t6, 0x2 add $t6, $t5, $t6 lw $t6, 0x0($t6) - jal model00019634 + jal modelasmIterateThings1 addi $gp, $zero, 0x0 mtc1 $zero, $f1 lwc1 $f0, 0x10($a2) @@ -247,7 +247,7 @@ glabel model00018680 sll $t6, $t6, 0x2 add $t6, $t5, $t6 lw $t6, 0x0($t6) - jal model000198dc + jal modelasmIterateThings2 addi $gp, $zero, 0x0 .L00018874: mtc1 $zero, $f1 @@ -289,7 +289,7 @@ glabel model00018680 sll $t6, $t6, 0x2 add $t6, $t5, $t6 lw $t6, 0x0($t6) - jal model00019634 + jal modelasmIterateThings1 addi $gp, $zero, 0x0 mtc1 $zero, $f1 lwc1 $f0, 0x34($a2) @@ -334,7 +334,7 @@ glabel model00018680 sll $t6, $t6, 0x2 add $t6, $t5, $t6 lw $t6, 0x0($t6) - jal model000198dc + jal modelasmIterateThings2 addi $gp, $zero, 0x0 .L000189cc: lw $a3, 0x8($a1) @@ -438,9 +438,9 @@ glabel model00018680 lhu $s3, 0x3c4($t0) lhu $s4, 0x3c6($t0) .L00018b3c: - jal model0001a024 + jal modelasmPrepareRotMtx360 sw $t0, 0x7e8($sp) - jal model00019f2c + jal modelasmMathPain2 nop mov.s $f16, $f0 mov.s $f17, $f1 @@ -448,11 +448,11 @@ glabel model00018680 mov.s $f19, $f3 or $t2, $s2, $zero or $t3, $s3, $zero - jal model0001a024 + jal modelasmPrepareRotMtx360 or $t4, $s4, $zero - jal model00019f2c + jal modelasmMathPain2 nop - jal model00019ddc + jal modelasmMathPain1 lwc1 $f30, 0x7e0($sp) addiu $t0, $zero, 0x1 sw $t0, 0x7e4($sp) @@ -461,7 +461,7 @@ glabel model00018680 swc1 $f1, 0x7ec($sp) swc1 $f2, 0x7f0($sp) swc1 $f3, 0x7f4($sp) - jal model0001a110 + jal modelasmMathPain4 nop j .L00018c6c nop @@ -516,9 +516,9 @@ glabel model00018680 add $s0, $zero, $t2 add $s1, $zero, $t3 add $s2, $zero, $t4 - jal model00019f98 + jal modelasmPrepareRotMtx180 add $s3, $zero, $t0 - jal model0001a0ac + jal modelasmMathPain3 add $t0, $zero, $s3 .L00018c6c: andi $t2, $s8, 0x2 @@ -576,7 +576,7 @@ glabel model00018680 lw $t0, 0x8($gp) beqz $t0, .L00018d48 nop - jal model0001a25c + jal modelasmFindNodeMtx nop b .L00018d4c nop @@ -587,7 +587,7 @@ glabel model00018680 lhu $t2, 0xe($t1) sll $t2, $t2, 0x6 lw $t1, 0xc($a1) - jal model0001a1c0 + jal modelasmMtxMultiply add $t1, $t1, $t2 lui $t3, %hi(g_ModelJointPositionedFunc) addiu $t3, $t3, %lo(g_ModelJointPositionedFunc) @@ -677,9 +677,9 @@ glabel model00018680 add $t2, $zero, $s0 add $t3, $zero, $s1 add $t4, $zero, $s2 - jal model0001a024 + jal modelasmPrepareRotMtx360 add $s0, $zero, $t0 - jal model00019f2c + jal modelasmMathPain2 add $t0, $zero, $s0 .L00018ecc: lui $at, 0x3f00 @@ -714,7 +714,7 @@ glabel model00018680 c.le.s $f6, $f7 bc1f .L00018f8c nop - jal model0001a2dc + jal modelasmAcosOrAsin nop mov.s $f17, $f0 mul.s $f12, $f6, $f8 @@ -744,12 +744,12 @@ glabel model00018680 mul.s $f3, $f3, $f8 add.s $f0, $f0, $f4 .L00018fb4: - jal model0001a110 + jal modelasmMathPain4 lw $t1, 0x4($gp) lhu $t2, 0x10($t1) sll $t2, $t2, 0x6 lw $t1, 0xc($a1) - jal model0001a1c0 + jal modelasmMtxMultiply add $t1, $t1, $t2 j .L00019574 nop @@ -769,11 +769,11 @@ glabel model00018680 lhu $s8, 0x0($t0) .L0001900c: syscall - jal model0001a25c + jal modelasmFindNodeMtx add $t0, $zero, $gp lui $t2, %hi(g_ModelDistanceDisabled) addiu $t2, $t2, %lo(g_ModelDistanceDisabled) - jal model00019d1c + jal modelasmGetNodeRwData lw $t1, 0x4($gp) lw $t2, 0x0($t2) bnez $t2, .L00019068 @@ -891,9 +891,9 @@ glabel model00018680 lhu $s3, 0x3c4($t0) lhu $s4, 0x3c6($t0) .L000191cc: - jal model0001a024 + jal modelasmPrepareRotMtx360 sw $t0, 0x7e8($sp) - jal model00019f2c + jal modelasmMathPain2 nop mov.s $f16, $f0 mov.s $f17, $f1 @@ -901,14 +901,14 @@ glabel model00018680 mov.s $f19, $f3 or $t2, $s2, $zero or $t3, $s3, $zero - jal model0001a024 + jal modelasmPrepareRotMtx360 or $t4, $s4, $zero - jal model00019f2c + jal modelasmMathPain2 nop - jal model00019ddc + jal modelasmMathPain1 lwc1 $f30, 0x7e0($sp) lw $t0, 0x7e8($sp) - jal model0001a110 + jal modelasmMathPain4 nop j .L000192a8 nop @@ -936,7 +936,7 @@ glabel model00018680 .L0001926c: andi $t3, $t3, 0xffff andi $t4, $t4, 0xffff - jal model00019f98 + jal modelasmPrepareRotMtx180 lhu $t2, 0x2($t0) b .L000192a0 nop @@ -946,13 +946,13 @@ glabel model00018680 lhu $s8, 0x0($t0) lhu $t4, 0x6($t0) lhu $t3, 0x4($t0) - jal model00019f98 + jal modelasmPrepareRotMtx180 lhu $t2, 0x2($t0) .L000192a0: - jal model0001a0ac + jal modelasmMathPain3 nop .L000192a8: - jal model00019d1c + jal modelasmGetNodeRwData mtc1 $zero, $f0 mov.s $f27, $f12 mov.s $f28, $f13 @@ -1066,7 +1066,7 @@ glabel model00018680 lhu $t2, 0x2($t1) sll $t2, $t2, 0x6 lw $t1, 0xc($a1) - jal model0001a1c0 + jal modelasmMtxMultiply add $t1, $t1, $t2 j .L00019574 nop @@ -1086,7 +1086,7 @@ glabel model00018680 lhu $s8, 0x0($t0) .L000194a0: syscall - jal model00019d1c + jal modelasmGetNodeRwData nop lw $t1, 0x0($v0) beqz $t1, .L00019574 @@ -1108,7 +1108,7 @@ glabel model00018680 j .L000194fc lw $t0, 0x0($a0) .L000194f4: - jal model0001a25c + jal modelasmFindNodeMtx nop .L000194fc: lw $t1, 0x4($gp) @@ -1127,13 +1127,13 @@ glabel model00018680 lhu $t2, 0xc($t1) sll $t2, $t2, 0x6 lw $t1, 0xc($a1) - jal model0001a1c0 + jal modelasmMtxMultiply add $t1, $t1, $t2 j .L00019574 nop j .L00019574 nop - jal model00019d1c + jal modelasmGetNodeRwData lw $t0, 0x4($gp) lw $t1, 0x0($v0) beqz $t1, .L00019570 @@ -1196,7 +1196,7 @@ glabel model00018680 addiu $sp, $sp, 0x800 syscall -glabel model00019634 +glabel modelasmIterateThings1 sw $ra, 0x7ac($sp) .L00019638: lbu $t7, 0x0($t2) @@ -1238,7 +1238,7 @@ glabel model00019634 j .L00019808 addi $t2, $t2, 0xc .L000196cc: - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x2($t2) add $s0, $zero, $v0 lbu $v1, 0x2($t2) @@ -1264,7 +1264,7 @@ glabel model00019634 addu $s3, $s3, $s4 addu $s0, $s0, $s3 andi $s0, $s0, 0xffff - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x5($t2) add $s1, $zero, $v0 lbu $v1, 0x5($t2) @@ -1290,7 +1290,7 @@ glabel model00019634 addu $s3, $s3, $s4 addu $s1, $s1, $s3 andi $s1, $s1, 0xffff - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x8($t2) add $s2, $zero, $v0 lbu $v1, 0x8($t2) @@ -1328,7 +1328,7 @@ glabel model00019634 j .L000198b4 addi $s2, $zero, 0x0 .L00019820: - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x2($t2) add $s0, $zero, $v0 lbu $v1, 0x0($t2) @@ -1340,7 +1340,7 @@ glabel model00019634 sub $v0, $v0, $t4 sllv $s0, $s0, $v0 andi $s0, $s0, 0xffff - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x5($t2) add $s1, $zero, $v0 lbu $v1, 0x3($t2) @@ -1352,7 +1352,7 @@ glabel model00019634 sub $v0, $v0, $t4 sllv $s1, $s1, $v0 andi $s1, $s1, 0xffff - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x8($t2) add $s2, $zero, $v0 lbu $v1, 0x6($t2) @@ -1377,7 +1377,7 @@ glabel model00019634 jr $ra nop -glabel model000198dc +glabel modelasmIterateThings2 sw $ra, 0x7ac($sp) .L000198e0: lbu $t7, 0x0($t2) @@ -1445,7 +1445,7 @@ glabel model000198dc j .L00019a64 addi $s2, $zero, 0x0 .L000199d0: - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x2($t2) add $s0, $zero, $v0 lbu $v1, 0x0($t2) @@ -1457,7 +1457,7 @@ glabel model000198dc sub $v0, $v0, $t4 sllv $s0, $s0, $v0 andi $s0, $s0, 0xffff - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x5($t2) add $s1, $zero, $v0 lbu $v1, 0x3($t2) @@ -1469,7 +1469,7 @@ glabel model000198dc sub $v0, $v0, $t4 sllv $s1, $s1, $v0 andi $s1, $s1, 0xffff - jal model00019be0 + jal modelasmReadFrameData lbu $v1, 0x8($t2) add $s2, $zero, $v0 lbu $v1, 0x6($t2) @@ -1588,7 +1588,7 @@ glabel model000198dc jr $ra nop -glabel model00019be0 +glabel modelasmReadFrameData beqz $v1, .L00019d14 addi $v0, $zero, 0x0 .L00019be8: @@ -1675,7 +1675,7 @@ glabel model00019be0 jr $ra nop -glabel model00019d1c +glabel modelasmGetNodeRwData addiu $sp, $sp, -32 sw $gp, 0x0($sp) sw $t0, 0x4($sp) @@ -1712,7 +1712,7 @@ glabel model00019d1c addiu $at, $zero, 0x17 bne $t1, $at, .L00019d84 nop - jal model00019d1c + jal modelasmGetNodeRwData nop lw $t3, 0x4($v0) .L00019db0: @@ -1781,7 +1781,7 @@ glabel modelGetNodeRwData addiu $sp, $sp, 0x10 #endif -glabel model00019ddc +glabel modelasmMathPain1 sw $ra, 0x7ac($sp) .L00019de0: mul.s $f5, $f16, $f0 @@ -1831,7 +1831,7 @@ glabel model00019ddc c.le.s $f6, $f7 bc1f .L00019f20 nop - jal model0001a2dc + jal modelasmAcosOrAsin nop mov.s $f20, $f0 jal sinf @@ -1872,7 +1872,7 @@ glabel model00019ddc j .L00019ed8 sub.s $f5, $f5, $f30 -glabel model00019f2c +glabel modelasmMathPain2 mul.s $f6, $f0, $f2 nop mul.s $f7, $f0, $f3 @@ -1901,7 +1901,7 @@ glabel model00019f2c jr $ra sub.s $f3, $f26, $f10 -glabel model00019f98 +glabel modelasmPrepareRotMtx180 add $t5, $zero, $ra lui $at, %hi(var7005422c) lwc1 $f29, %lo(var7005422c)($at) @@ -1938,7 +1938,7 @@ glabel model00019f98 jr $ra nop -glabel model0001a024 +glabel modelasmPrepareRotMtx360 add $t5, $zero, $ra lui $at, %hi(var70054234) lwc1 $f29, %lo(var70054234)($at) @@ -1974,7 +1974,7 @@ glabel model0001a024 jr $ra nop -glabel model0001a0ac +glabel modelasmMathPain3 mul.s $f6, $f1, $f5 nop mul.s $f7, $f0, $f5 @@ -2001,7 +2001,7 @@ glabel model0001a0ac jr $ra sub.s $f19, $f19, $f8 -glabel model0001a110 +glabel modelasmMathPain4 mul.s $f4, $f0, $f0 nop mul.s $f5, $f1, $f1 @@ -2047,7 +2047,7 @@ glabel model0001a110 jr $ra sub.s $f20, $f20, $f26 -glabel model0001a1c0 +glabel modelasmMtxMultiply addiu $t2, $zero, 0x3 .L0001a1c4: lwc1 $f0, 0x0($t0) @@ -2089,7 +2089,7 @@ glabel model0001a1c0 jr $ra swc1 $f31, 0x30($t1) -glabel model0001a25c +glabel modelasmFindNodeMtx .L0001a25c: lh $t1, 0x0($t0) andi $t1, $t1, 0xff @@ -2127,7 +2127,7 @@ glabel model0001a25c jr $ra add $t0, $zero, $zero -glabel model0001a2dc +glabel modelasmAcosOrAsin lui $at, %hi(var7005423c) lwc1 $f7, %lo(var7005423c)($at) mul.s $f7, $f6, $f7 @@ -2204,12 +2204,12 @@ glabel cosf glabel sinf mfc1 $t0, $f12 - nop + nop sra $t0, $t0, 22 andi $t0, $t0, 0x1ff slti $at, $t0, 255 beqz $at, .L0001a454 - nop + nop slti $at, $t0, 230 bnez $at, .L0001a4f0 mov.s $f0, $f12 @@ -2229,7 +2229,7 @@ glabel sinf mul.s $f15, $f15, $f14 add.s $f15, $f13, $f15 mul.s $f15, $f15, $f14 - nop + nop mul.s $f15, $f15, $f12 jr $ra add.s $f0, $f15, $f12 @@ -2267,7 +2267,7 @@ glabel sinf mul.s $f15, $f15, $f14 add.s $f15, $f13, $f15 mul.s $f15, $f15, $f14 - nop + nop mul.s $f15, $f15, $f12 andi $t1, $t1, 1 add.s $f0, $f15, $f12 @@ -2275,4 +2275,4 @@ glabel sinf neg.s $f0, $f0 .L0001a4f0: jr $ra - nop + nop diff --git a/src/lib/modelasm_c.c b/src/lib/modelasm_c.c new file mode 100644 index 000000000..a85a4952f --- /dev/null +++ b/src/lib/modelasm_c.c @@ -0,0 +1,1647 @@ +#include +#include "constants.h" +#include "bss.h" +#include "data.h" +#include "lib/model.h" +#include "lib/mtx.h" +#include "types.h" + +struct t0slot { + u16 unk00; + u16 unk02; + u16 unk04; + u16 unk06; +}; + +struct t0slot *t0slot; +u8 *t2ptr8; +s32 t3; +u8 *t3ptr8; +s32 t4; +u8 *t6ptr8; +s32 v1; +s32 s0; +s32 s1; +s32 s2; +s32 s3; +s32 s4; +s32 sr8; +s32 f0int; +f32 f0; +f32 f1; +f32 f2; +f32 f3; +f32 f4; +f32 f5; + +// f12-f23 are used as rotation matrix +f32 f12; +f32 f13; +f32 f14; +f32 f15; +f32 f16; +f32 f17; +f32 f18; +f32 f19; +f32 f20; +f32 f21; +f32 f22; +f32 f23; + +s32 gp; + +static bool modelasmIterateThings1(void); +static bool modelasmIterateThings2(void); +static u32 modelasmReadFrameData(void); +static union modelrwdata *modelasmGetNodeRwData(struct model *model, struct modelnode *node, bool is_head); +static void modelasmMathPain1(f32 f30); +static void modelasmMathPain2(void); +static void modelasmPrepareRotMtx180(s32 t2, s32 t3, s32 t4); +static void modelasmPrepareRotMtx360(s32 t2, s32 t3, s32 t4); +static void modelasmMathPain3(void); +static void modelasmMathPain4(void); +static void modelasmMtxMultiply(Mtxf *src, Mtxf *dst); +static Mtxf *modelasmFindNodeMtx(struct model *model, struct modelnode *node); +static f32 modelasmAcosOrAsin(f32 f6); + +/** + * Reads animation data for the given model and applies matrix transformations + * for each part. It factors merging between two animations too. + * + * The game code is able to set g_ModelJointPositionedFunc to a callback, + * and this function will execute that callback for every positioned joint. + * + * Returns true if succeeded, or false if the caller should do some kind of + * simple/generic calculation. + */ +bool modelasm00018680(struct modelrenderdata *renderdata, struct model *model) +{ + bool sp7f8 = false; + f32 sp7e8f32; + struct t0slot *sp7e8slot; + f32 sp7f4; + f32 sp7f0; + f32 sp7ec; + bool sp7e4; + struct t0slot sp00[240]; + struct modelnode *node; + struct anim *anim; + struct skeleton *skeleton; + struct modeldef *modeldef; + union modelrwdata *rwdata; + f32 f6; + f32 f7; + f32 f8; + f32 f9; + f32 f10; + f32 f30; + Mtxf *t0mtx; + Mtxf *t1mtx; + s32 t1; + s32 t2; + u8 *s0ptr8; + s32 i; + f32 yrot; + + for (i = 0; i < model->definition->nummatrices; i++) { + sp00[i].unk00 = 0; + } + + anim = model->anim; + + if (anim) { + t0slot = &sp00[0]; + t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]]; + t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]] + g_Anims[anim->animnum].headerlen; + t4 = g_Anims[anim->animnum].framelen; + + if (t2ptr8 != t3ptr8) { + t6ptr8 = g_AnimFrameBytes[anim->frameslot1]; + + if (!modelasmIterateThings1()) { + return false; + } + + if (anim->frac != 0.0f) { + for (i = 0; i < model->definition->nummatrices; i++) { + sp00[120 + i].unk00 = 0; + } + + f0int = anim->frac * 4096; + + t0slot = &sp00[0]; + t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]]; + t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum]] + g_Anims[anim->animnum].headerlen; + t4 = g_Anims[anim->animnum].framelen; + + if (t2ptr8 != t3ptr8) { + t6ptr8 = g_AnimFrameBytes[anim->frameslot2]; + + if (!modelasmIterateThings2()) { + return false; + } + } + } + } + + f30 = anim->fracmerge; + + if (anim->fracmerge != 0.0f) { + t0slot = &sp00[120]; + t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]]; + t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]] + g_Anims[anim->animnum2].headerlen; + t4 = g_Anims[anim->animnum2].framelen; + + if (t2ptr8 != t3ptr8) { + t6ptr8 = g_AnimFrameBytes[anim->frameslot3]; + + if (!modelasmIterateThings1()) { + return false; + } + + if (anim->frac2 != 0.0f) { + t0slot = &sp00[120]; + f0int = anim->frac2 * 4096; + t2ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]]; + t3ptr8 = g_AnimHeaderBytes[g_AnimToHeaderSlot[anim->animnum2]] + g_Anims[anim->animnum2].headerlen; + t4 = g_Anims[anim->animnum2].framelen; + + if (t2ptr8 != t3ptr8) { + t6ptr8 = g_AnimFrameBytes[anim->frameslot4]; + + if (!modelasmIterateThings2()) { + return false; + } + } + } + } + } + } + + modeldef = model->definition; + node = modeldef->rootnode; + skeleton = modeldef->skel; + + while (node) { + switch (node->type & 0xff) { + case MODELNODETYPE_POSITION: + sp7e4 = false; + + if (model) { + t1 = node->rodata->position.part; + + if (anim) { + if (f30 != 0.0f) { + if (anim->flip) { + t2ptr8 = skeleton->things[t1]; + t0slot = &sp00[t2ptr8[1]]; + + sr8 = t0slot->unk00; + t4 = t0slot->unk06; + t3 = t0slot->unk04; + t2 = t0slot->unk02; + + if (t4 != 0) { + t4 = (0x10000 - t4) & 0xffff; + } + + if (t3 != 0) { + t3 = (0x10000 - t3) & 0xffff; + } + } else { + t0slot = &sp00[t1]; + + sr8 = t0slot->unk00; + t2 = t0slot->unk02; + t3 = t0slot->unk04; + t4 = t0slot->unk06; + } + + if (anim->flip2) { + s0ptr8 = skeleton->things[t1]; + t0slot = &sp00[s0ptr8[1]]; + + s4 = t0slot[120].unk06; + s3 = t0slot[120].unk04; + s0 = t0slot[0].unk02; + s2 = t0slot[120].unk02; + + if (s4 != 0) { + s4 = (0x10000 - s4) & 0xffff; + } + + if (s3 != 0) { + s3 = (0x10000 - s3) & 0xffff; + } + } else { + t0slot = &sp00[t1]; + + s2 = t0slot[120].unk02; + s3 = t0slot[120].unk04; + s4 = t0slot[120].unk06; + } + + sp7e8slot = t0slot; + modelasmPrepareRotMtx360(t2, t3, t4); + modelasmMathPain2(); + + f16 = f0; + f17 = f1; + f18 = f2; + f19 = f3; + + t2 = s2; + t3 = s3; + t4 = s4; + + modelasmPrepareRotMtx360(t2, t3, t4); + modelasmMathPain2(); + modelasmMathPain1(f30); + + sp7e4 = true; + t0slot = sp7e8slot; + + sp7e8f32 = f0; + sp7ec = f1; + sp7f0 = f2; + sp7f4 = f3; + + modelasmMathPain4(); + } else { + if (anim->flip) { + t2ptr8 = skeleton->things[t1]; + t0slot = &sp00[t2ptr8[1]]; + + sr8 = t0slot->unk00; + t4 = t0slot->unk06; + t3 = t0slot->unk04; + t2 = t0slot->unk02; + + if (t4 != 0) { + t4 = (0x10000 - t4) & 0xffff; + } + + if (t3 != 0) { + t3 = (0x10000 - t3) & 0xffff; + } + } else { + t0slot = &sp00[t1]; + + sr8 = t0slot->unk00; + t4 = t0slot->unk06; + t3 = t0slot->unk04; + t2 = t0slot->unk02; + } + + s0 = t2; + + if ((sr8 & 1) == 0) { + f12 = 1; + f13 = 0; + f14 = 0; + + f15 = 0; + f16 = 1; + f17 = 0; + + f18 = 0; + f19 = 0; + f20 = 1; + } else { + s0 = t2; + s1 = t3; + s2 = t4; + + modelasmPrepareRotMtx180(t2, t3, t4); + modelasmMathPain3(); + } + } + } else { + f12 = 1; + f13 = 0; + f14 = 0; + + f15 = 0; + f16 = 1; + f17 = 0; + + f18 = 0; + f19 = 0; + f20 = 1; + + t0slot = &sp00[t1]; + sr8 = t0slot->unk00; + } + + if (sr8 & 2) { + t2 = *(s16 *) &t0slot[60].unk00; + t3 = *(s16 *) &t0slot[60].unk02; + t4 = *(s16 *) &t0slot[60].unk04; + + if (node == modeldef->rootnode) { + f21 = t2 * anim->animscale; + f22 = t3 * anim->animscale; + f23 = t4 * anim->animscale; + } else { + f0 = t2 * anim->animscale; + f1 = t3 * anim->animscale; + f2 = t4 * anim->animscale; + + f21 = f0 + node->rodata->position.pos.x; + f22 = f1 + node->rodata->position.pos.y; + f23 = f2 + node->rodata->position.pos.z; + } + } else { + if (node != modeldef->rootnode) { + f21 = node->rodata->position.pos.x; + f22 = node->rodata->position.pos.y; + f23 = node->rodata->position.pos.z; + } else { + f21 = 0; + f22 = 0; + f23 = 0; + } + } + + t0mtx = node->parent ? modelasmFindNodeMtx(model, node->parent) : renderdata->unk00; + t1mtx = &model->matrices[node->rodata->position.mtxindex0]; + + modelasmMtxMultiply(t0mtx, t1mtx); + + if (g_ModelJointPositionedFunc) { + g_ModelJointPositionedFunc(node->rodata->position.mtxindex0, &model->matrices[node->rodata->position.mtxindex0]); + } + + if (node->type & MODELNODETYPE_0100) { + if (sp7e4) { + f0 = sp7e8f32; + f1 = sp7ec; + f2 = sp7f0; + f3 = sp7f4; + } else { + t2 = s0; + t3 = s1; + t4 = s2; + modelasmPrepareRotMtx360(t2, t3, t4); + modelasmMathPain2(); + } + + f4 = 0; + f6 = f0; + f5 = 1; + + if (f6 < 0.0f) { + f6 = -f6; + f5 = -f5; + } + + if (f6 < -0.99994999170303f) { + f0 *= 0.5f; + f4 = f5 * 0.5f; + f1 *= 0.5f; + f2 *= 0.5f; + f3 *= 0.5f; + f0 -= f4; + } else if (f6 > 0.99994999170303f) { + f0 *= 0.5f; + f1 *= 0.5f; + f2 *= 0.5f; + f3 *= 0.5f; + f4 = f5 * 0.5f; + f0 += f4; + } else { + f7 = modelasmAcosOrAsin(f6); + f17 = f0; + f12 = f6 * 0.5f; + s1 = t1; + f0 = sinf(f12); + f3 *= f0; + f2 *= f0; + t1 = s1; + f1 *= f0; + f5 *= f0; + f0 *= f17; + f0 += f5; + } + + modelasmMathPain4(); + t1mtx = &model->matrices[node->rodata->position.mtxindex1]; + modelasmMtxMultiply(t0mtx, t1mtx); + } + } + break; + case MODELNODETYPE_DISTANCE: + t0mtx = modelasmFindNodeMtx(model, node); + + rwdata = modelasmGetNodeRwData(model, node, sp7f8); + f0 = 0; + + if (!g_ModelDistanceDisabled && t0mtx) { + f0 = -t0mtx->m[3][2] * g_Vars.currentplayer->c_lodscalez * g_ModelDistanceScale; + } + + if ((node->rodata->distance.near == 0.0f || f0 > node->rodata->distance.near * model->scale) + && f0 <= node->rodata->distance.far * model->scale) { + rwdata->distance.visible = true; + node->child = node->rodata->distance.target; + } else { + rwdata->distance.visible = false; + node->child = NULL; + } + break; + case MODELNODETYPE_CHRINFO: + if (model) { + t1 = node->rodata->chrinfo.animpart; + + if (anim) { + if (f30 != 0.0f) { + if (anim->flip) { + t2ptr8 = skeleton->things[t1]; + t0slot = &sp00[t2ptr8[1]]; + + sr8 = t0slot->unk00; + t4 = t0slot->unk06; + t3 = t0slot->unk04; + t2 = t0slot->unk02; + + if (t4 != 0) { + t4 = (0x10000 - t4) & 0xffff; + } + + if (t3 != 0) { + t3 = (0x10000 - t3) & 0xffff; + } + } else { + t0slot = &sp00[t1]; + + sr8 = t0slot->unk00; + t2 = t0slot->unk02; + t3 = t0slot->unk04; + t4 = t0slot->unk06; + } + + if (anim->flip2) { + s0ptr8 = skeleton->things[t1]; + t0slot = &sp00[s0ptr8[1]]; + + s4 = t0slot[120].unk06; + s3 = t0slot[120].unk04; + s0 = t0slot[0].unk02; + s2 = t0slot[120].unk02; + + if (s4 != 0) { + s4 = (0x10000 - s4) & 0xffff; + } + + if (s3 != 0) { + s3 = (0x10000 - s3) & 0xffff; + } + } else { + t0slot = &sp00[t1]; + + s2 = t0slot[120].unk02; + s3 = t0slot[120].unk04; + s4 = t0slot[120].unk06; + } + + sp7e8slot = t0slot; + modelasmPrepareRotMtx360(t2, t3, t4); + modelasmMathPain2(); + + f16 = f0; + f17 = f1; + f18 = f2; + f19 = f3; + + t2 = s2; + t3 = s3; + t4 = s4; + + modelasmPrepareRotMtx360(t2, t3, t4); + modelasmMathPain2(); + modelasmMathPain1(f30); + t0slot = sp7e8slot; + modelasmMathPain4(); + } else { + if (anim->flip) { + t2ptr8 = skeleton->things[t1]; + t0slot = &sp00[t2ptr8[1]]; + + sr8 = t0slot->unk00; + t4 = t0slot->unk06; + t3 = t0slot->unk04; + t2 = t0slot->unk02; + + if (t4 != 0) { + t4 = (0x10000 - t4) & 0xffff; + } + + if (t3 != 0) { + t3 = (0x10000 - t3) & 0xffff; + } + + modelasmPrepareRotMtx180(t2, t3, t4); + } else { + t0slot = &sp00[t1]; + + sr8 = t0slot->unk00; + t4 = t0slot->unk06; + t3 = t0slot->unk04; + t2 = t0slot->unk02; + + modelasmPrepareRotMtx180(t2, t3, t4); + } + + modelasmMathPain3(); + } + } else { + f12 = 1; + f13 = 0; + f14 = 0; + + f15 = 0; + f16 = 1; + f17 = 0; + + f18 = 0; + f19 = 0; + f20 = 1; + + t0slot = &sp00[t1]; + sr8 = t0slot->unk00; + } + + f0 = 0; + + rwdata = modelasmGetNodeRwData(model, node, sp7f8); + + yrot = rwdata->chrinfo.yrot; + + if (rwdata->chrinfo.unk18 != 0.0f) { + f5 = rwdata->chrinfo.unk1c - rwdata->chrinfo.yrot; + + if (f5 < 0.0f) { + f5 += M_TAU; + } + + if (f5 >= M_PI) { + f5 *= rwdata->chrinfo.unk18; + yrot += f5; + + if (yrot > M_TAU) { + yrot -= M_TAU; + } + } else { + f5 = M_TAU - f5; + f5 *= rwdata->chrinfo.unk18; + yrot -= f5; + + if (yrot < 0.0f) { + yrot += M_TAU; + } + } + } + + f1 = sinf(yrot); + f0 = sinf(yrot + 1.570796251297f); + + f2 = -f1; + + f21 = rwdata->chrinfo.pos.x; + f22 = rwdata->chrinfo.pos.y; + f23 = rwdata->chrinfo.pos.z; + + f3 = f0 * f12; + f4 = f1 * f14; + f5 = f0 * f15; + f3 = f3 + f4; + f6 = f1 * f17; + f7 = f0 * f18; + f5 = f5 + f6; + f8 = f1 * f20; + f9 = f2 * f12; + f7 = f7 + f8; + f10 = f0 * f14; + f4 = f2 * f15; + f14 = f9 + f10; + f6 = f0 * f17; + f8 = f2 * f18; + f17 = f4 + f6; + f10 = f0 * f20; + f12 = f3; + f20 = f8 + f10; + f15 = f5; + f18 = f7; + + if (model->scale != 1.0f) { + f12 *= model->scale; + f13 *= model->scale; + f14 *= model->scale; + f15 *= model->scale; + f16 *= model->scale; + f17 *= model->scale; + f18 *= model->scale; + f19 *= model->scale; + f20 *= model->scale; + } + + t0mtx = renderdata->unk00; + t1mtx = &model->matrices[node->rodata->chrinfo.mtxindex]; + + modelasmMtxMultiply(t0mtx, t1mtx); + } + break; + case MODELNODETYPE_HEADSPOT: + rwdata = modelasmGetNodeRwData(model, node, sp7f8); + + if (rwdata->headspot.headmodeldef) { + struct modelnode *iternode = rwdata->headspot.headmodeldef->rootnode; + sp7f8 = true; + node->child = iternode; + + while (iternode) { + iternode->parent = node; + iternode = iternode->next; + } + } + break; + case MODELNODETYPE_POSITIONHELD: + t0mtx = node->parent ? modelasmFindNodeMtx(model, node->parent) : renderdata->unk00; + + f12 = 1; + f13 = 0; + f14 = 0; + + f15 = 0; + f16 = 1; + f17 = 0; + + f18 = 0; + f19 = 0; + f20 = 1; + + f21 = node->rodata->positionheld.pos.x; + f22 = node->rodata->positionheld.pos.y; + f23 = node->rodata->positionheld.pos.z; + + t1mtx = &model->matrices[node->rodata->positionheld.mtxindex]; + + modelasmMtxMultiply(t0mtx, t1mtx); + break; + case MODELNODETYPE_REORDER: + break; + case MODELNODETYPE_TOGGLE: + rwdata = modelasmGetNodeRwData(model, node, sp7f8); + + node->child = rwdata->toggle.visible ? node->rodata->toggle.target : NULL; + break; + } + + if (node->child) { + node = node->child; + } else { + while (true) { + if (node->next) { + node = node->next; + break; + } else { + node = node->parent; + + if (node) { + if ((node->type & 0xff) == MODELNODETYPE_HEADSPOT) { + // @bug: + // sp7f8 tracks whether we are under the head node + // which allows modelasmGetNodeRwData to avoid + // searching for the head node if we're already + // above it. The code here is ascending back out of + // the head node, so it should be setting it to + // false here. + sp7f8 = true; + } + } else { + return true; + } + } + } + } + } + + return true; +} + +/** + * Expects: + * t0 = pointer to stack slots + * t2 = pointer to anim header bytes + * t3 = pointer to end of anim header + * t6 = pointer to anim frame bytes + */ +static bool modelasmIterateThings1(void) +{ + s32 t7; + s32 t8; + u32 v0; + + gp = 0; + + do { + t7 = *t2ptr8; + t2ptr8++; + t0slot->unk00 = t7; + + if (t7 > 15) { + return false; + } + + if (t7 & 2) { + // 0, 1, 2 + v1 = t2ptr8[2]; + s0 = modelasmReadFrameData(); + v1 = t2ptr8[2]; + s3 = 1; + + if (v1 < 16) { + v0 = v1 - 1; + s3 <<= v0; + s4 = 16; + + if (s0 & s3) { + s4 -= v1; + v0 = (1 << s4) - 1; + v0 <<= v1; + s0 |= v0; + } + } + + s3 = t2ptr8[0] << 8; + s4 = t2ptr8[1]; + s3 += s4; + s0 += s3; + s0 &= 0xffff; + + // 3, 4, 5 + v1 = t2ptr8[5]; + s1 = modelasmReadFrameData(); + v1 = t2ptr8[5]; + s3 = 1; + + if (v1 < 16) { + v0 = v1 - 1; + s3 <<= v0; + s4 = 16; + + if (s1 & s3) { + s4 -= v1; + v0 = (1 << s4) - 1; + v0 <<= v1; + s1 |= v0; + } + } + + s3 = t2ptr8[3] << 8; + s4 = t2ptr8[4]; + s3 += s4; + s1 += s3; + s1 &= 0xffff; + + // 6, 7, 8 + v1 = t2ptr8[8]; + s2 = modelasmReadFrameData(); + v1 = t2ptr8[8]; + s3 = 1; + + if (v1 < 16) { + v0 = v1 - 1; + s3 <<= v0; + s4 = 16; + + if (s2 & s3) { + s4 -= v1; + v0 = (1 << s4) - 1; + v0 <<= v1; + s2 |= v0; + } + } + + s3 = t2ptr8[6] << 8; + s4 = t2ptr8[7]; + s3 += s4; + s2 += s3; + s2 &= 0xffff; + + t2ptr8 += 9; + + t0slot[60].unk00 = s0; + t0slot[60].unk02 = s1; + t0slot[60].unk04 = s2; + } else { + s0 = 0; + s1 = 0; + s2 = 0; + + if (t7 & 8) { + v0 = t2ptr8[2] + t2ptr8[5] + t2ptr8[8] + t2ptr8[11]; + v1 = t2ptr8[11]; + + if (v0 >= gp) { + v0 -= gp; + sr8 = 0; + t8 = v0 >> 3; + t6ptr8 += t8; + t8 <<= 3; + v0 -= t8; + sr8 = t6ptr8[0]; + gp = 8; + t6ptr8++; + gp -= v0; + } + + t2ptr8 += 12; + } + } + + if (t7 & 1) { + v1 = t2ptr8[2]; + s0 = modelasmReadFrameData(); + s0 += (t2ptr8[0] << 8) + t2ptr8[1]; + v0 = 16 - t4; + s0 = (s0 << v0) & 0xffff; + + v1 = t2ptr8[5]; + s1 = modelasmReadFrameData(); + s1 += (t2ptr8[3] << 8) + t2ptr8[4]; + v0 = 16 - t4; + s1 = (s1 << v0) & 0xffff; + + v1 = t2ptr8[8]; + s2 = modelasmReadFrameData(); + s2 += (t2ptr8[6] << 8) + t2ptr8[7]; + v0 = 16 - t4; + s2 = (s2 << v0) & 0xffff; + + t2ptr8 += 9; + } else { + s0 = 0; + s1 = 0; + s2 = 0; + } + + t0slot->unk02 = s0; + t0slot->unk04 = s1; + t0slot->unk06 = s2; + t0slot++; + } while (t2ptr8 < t3ptr8); + + return true; +} + +/** + * Expects: + * t0 = pointer to stack slots + * t2 = pointer to anim header bytes + * t3 = pointer to end of anim header + * t4 = frame length + * t6 = pointer to anim frame bytes + * f0 containing an integer + */ +static bool modelasmIterateThings2(void) +{ + s32 t7; + s32 t8; + s32 s5; + u32 v0; + + gp = 0; + + do { + t7 = t2ptr8[0]; + t2ptr8++; + + if (t7 > 15) { + return false; + } + + if ((t7 & 2) == 0) { + s0 = 0; + s1 = 0; + s2 = 0; + + if (t7 & 8) { + v0 = t2ptr8[2] + t2ptr8[5] + t2ptr8[8] + t2ptr8[11]; + + if (v0 >= gp) { + v0 -= gp; + sr8 = 0; + t8 = v0 >> 3; + t6ptr8 += t8; + t8 <<= 3; + v0 -= t8; + sr8 = t6ptr8[0]; + gp = 8; + t6ptr8++; + gp -= v0; + } else { + v0 -= gp; + } + + t2ptr8 += 12; + } + } else { + v0 = t2ptr8[2] + t2ptr8[5] + t2ptr8[8]; + + if (v0 >= gp) { + v0 -= gp; + sr8 = 0; + t8 = v0 >> 3; + t6ptr8 += t8; + t8 <<= 3; + v0 -= t8; + sr8 = t6ptr8[0]; + gp = 8; + t6ptr8++; + gp -= v0; + } else { + v0 -= gp; + } + + t2ptr8 += 9; + } + + if ((t7 & 1) == 0) { + s0 = 0; + s1 = 0; + s2 = 0; + } else { + v1 = t2ptr8[2]; + s0 = modelasmReadFrameData(); + s0 += (t2ptr8[0] << 8) + t2ptr8[1]; + v0 = 16 - t4; + s0 = (s0 << v0) & 0xffff; + + v1 = t2ptr8[5]; + s1 = modelasmReadFrameData(); + s1 += (t2ptr8[3] << 8) + t2ptr8[4]; + v0 = 16 - t4; + s1 = (s1 << v0) & 0xffff; + + v1 = t2ptr8[8]; + s2 = modelasmReadFrameData(); + s2 += (t2ptr8[6] << 8) + t2ptr8[7]; + v0 = 16 - t4; + s2 = (s2 << v0) & 0xffff; + + t2ptr8 += 9; + } + + s3 = f0int; + v1 = 0x10000; + + // 02 + s4 = t0slot->unk02; + s5 = s0 - s4; + + if (s5 < 0) { + s5 += 0x10000; + } + + if (s5 < 0x8000) { + s5 *= s3; + s5 >>= 12; + s0 = s4 + s5; + + if (s0 >= 0x10000) { + s0 -= 0x10000; + } + } else { + s5 = 0x10000 - s5; + s5 *= s3; + s5 >>= 12; + s0 = s4 - s5; + + if (s0 < 0) { + s0 += 0x10000; + } + } + + // 04 + s4 = t0slot->unk04; + s5 = s1 - s4; + + if (s5 < 0) { + s5 += 0x10000; + } + + if (s5 < 0x8000) { + s5 *= s3; + s5 >>= 12; + s1 = s4 + s5; + + if (s1 >= 0x10000) { + s1 -= 0x10000; + } + } else { + s5 = 0x10000 - s5; + s5 *= s3; + s5 >>= 12; + s1 = s4 - s5; + + if (s1 < 0) { + s1 += 0x10000; + } + } + + // 06 + s4 = t0slot->unk06; + s5 = s2 - s4; + + if (s5 < 0) { + s5 += 0x10000; + } + + if (s5 < 0x8000) { + s5 *= s3; + s5 >>= 12; + s2 = s4 + s5; + + if (s2 >= 0x10000) { + s2 -= 0x10000; + } + } else { + s5 = 0x10000 - s5; + s5 *= s3; + s5 >>= 12; + s2 = s4 - s5; + + if (s2 < 0) { + s2 += 0x10000; + } + } + + t0slot->unk02 = s0; + t0slot->unk04 = s1; + t0slot->unk06 = s2; + t0slot++; + } while (t2ptr8 < t3ptr8); + + return true; +} + +/** + * Expects: t3 t6 v1 gp s8 + */ +static u32 modelasmReadFrameData(void) +{ + u32 v0 = 0; + s32 s6; + + if (!v1) { + return 0; + } + + while (v1 > gp) { + v1 -= gp; + v0 |= (((1 << gp) - 1) & sr8) << v1; + s6 = t3ptr8 - t6ptr8; + + if (s6 >= 4) { + s6 = 4; + } + + sr8 = ((uintptr_t) t6ptr8 & 3) - 4; + sr8 = -sr8; + + if (sr8 != 0 && sr8 < s6) { + s6 = sr8; + } + + switch (s6) { + case 1: // 19c64 + sr8 = t6ptr8[0]; + t6ptr8++; + gp = 8; + break; + case 2: // 19c70 + sr8 = (t6ptr8[0] << 8) | t6ptr8[1]; + t6ptr8 += 2; + gp = 16; + break; + case 3: // 19c88 + sr8 = (t6ptr8[0] << 16) | (t6ptr8[1] << 8) | t6ptr8[2]; + t6ptr8 += 3; + gp = 24; + break; + case 4: // 19cac + sr8 = (t6ptr8[0] << 24) | (t6ptr8[1] << 16) | (t6ptr8[2] << 8) | t6ptr8[3]; + t6ptr8 += 4; + gp = 32; + break; + } + } + + gp -= v1; + + if (v1) { + v0 |= (sr8 >> gp) & ((1 << v1) - 1); + } + + return v0; +} + +/** + * Indexed by node type. + * + * Each value is the byte offset into the rodata struct where that node type's + * rwdataindex property can be found, or 0xff is there is none. + */ +u8 var8005ef90[] = { + 0xff, 0x08, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x0c, 0x22, 0xff, 0x44, + 0x20, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x04, 0xff, + 0xff, 0xff, 0xff, 0x00, + 0x14, 0x00, +}; + +static union modelrwdata *modelasmGetNodeRwData(struct model *model, struct modelnode *node, bool is_head) +{ + u32 index = 0; + union modelrwdata **rwdatas = model->rwdatas; + u8 type = node->type & 0xff; + + if (type < ARRAYCOUNT(var8005ef90)) { + if (var8005ef90[type] != 0xff) { + index = *(u16 *) ((uintptr_t) node->rodata + var8005ef90[type]); + } + } + + if (is_head) { + while (node->parent) { + node = node->parent; + + if ((node->type & 0xff) == MODELNODETYPE_HEADSPOT) { + union modelrwdata *tmp = modelasmGetNodeRwData(model, node, false); + rwdatas = tmp->headspot.rwdatas; + break; + } + } + } + + return (union modelrwdata *) &rwdatas[index]; +} + +#if VERSION < VERSION_NTSC_1_0 +void *modelGetNodeRwData(struct model *model, struct modelnode *node) +{ + u32 index = 0; + union modelrwdata **rwdatas = model->rwdatas; + u8 type = node->type & 0xff; + + if (type < ARRAYCOUNT(var8005ef90)) { + if (var8005ef90[type] != 0xff) { + index = *(u16 *) ((uintptr_t) node->rodata + var8005ef90[type]); + } + } + + if (model->unk00) { + while (node->parent) { + node = node->parent; + + if ((node->type & 0xff) == MODELNODETYPE_HEADSPOT) { + struct modelrwdata_headspot *tmp = modelGetNodeRwData(model, node); + rwdatas = tmp->rwdatas; + break; + } + } + } + + return &rwdatas[index]; +} +#endif + +/** + * Expects: f0-f3, f16-f22 + */ +static void modelasmMathPain1(f32 f30) +{ + f32 f6; + f32 f7; + f32 f8; + f32 f9; + + f4 = 0; + + while (true) { + f5 = f16 * f0; + f6 = f17 * f1; + f7 = f18 * f2; + f6 = f5 + f6; + f5 = f19 * f3; + f6 = f6 + f7; + f6 = f6 + f5; + + if (f6 >= 0.0f) { + break; + } + + f0 = -f0; + f1 = -f1; + f2 = -f2; + f3 = -f3; + } + + if (f6 < -0.99994999170303f) { + f6 = f30 * f16; + f5 = f5 - f30; + f7 = f5 * f0; + f0 = f7 - f6; + f6 = f30 * f17; + f7 = f5 * f1; + f8 = f30 * f18; + f1 = f7 - f6; + f9 = f5 * f2; + f6 = f30 * f19; + f2 = f9 - f8; + f7 = f5 * f3; + f2 = f7 - f6; + return; + } + + if (f6 <= 0.99994999170303f) { + f7 = modelasmAcosOrAsin(f6); + f20 = f0; + f21 = sinf(f7); + f22 = sinf((1.0f - f30) * f7); + f0 = sinf(f7 * f30); + + f5 = f22 / f21; + f30 = f0 / f21; + f0 = f20; + } else { + f5 = 1.0f - f30; + } + + f6 = f5 * f16; + f7 = f30 * f0; + f8 = f5 * f17; + f0 = f6 + f7; + f9 = f30 * f1; + f6 = f5 * f18; + f1 = f8 + f9; + f7 = f30 * f2; + f8 = f5 * f19; + f2 = f6 + f7; + f9 = f30 * f3; + f3 = f8 + f9; +} + +/** + * Expects: f0 f1 f2 f3 f4 f5 + */ +static void modelasmMathPain2(void) +{ + f32 f6; + f32 f7; + f32 f8; + f32 f9; + f32 f10; + f32 f11; + f32 f26; + + f6 = f0 * f2; + f7 = f0 * f3; + f8 = f1 * f2; + f9 = f1 * f3; + f0 = f6 * f4; + f1 = f9 * f5; + f2 = f8 * f4; + f0 = f0 + f1; + f1 = f7 * f5; + f3 = f7 * f5; + f10 = f7 * f4; + f1 = f2 - f1; + f11 = f8 * f5; + f26 = f6 * f5; + f2 = f10 + f11; + f10 = f9 * f4; + f3 = f26 - f10; +} + +static void modelasmPrepareRotMtx180(s32 t2, s32 t3, s32 t4) +{ + // Very close to: 1.0f / (180 * 180 / M_PI) + f32 f8 = t4 * 0.000095873801910784f; + f32 f7 = t3 * 0.000095873801910784f; + f32 f6 = t2 * 0.000095873801910784f; + + f5 = sinf(f8); + f4 = sinf(f8 + 1.570796251297f); + f3 = sinf(f7); + f2 = sinf(f7 + 1.570796251297f); + f1 = sinf(f6); + f0 = sinf(f6 + 1.570796251297f); +} + +static void modelasmPrepareRotMtx360(s32 t2, s32 t3, s32 t4) +{ + // Very close to: 1.0f / (360 * 180 / M_PI) + f32 f8 = t4 * 0.000047936900955392f; + f32 f7 = t3 * 0.000047936900955392f; + f32 f6 = t2 * 0.000047936900955392f; + + f5 = sinf(f8); + f4 = sinf(f8 + 1.5707963705063f); + f3 = sinf(f7); + f2 = sinf(f7 + 1.5707963705063f); + f1 = sinf(f6); + f0 = sinf(f6 + 1.5707963705063f); +} + +/** + * Expects: f0 f1 f2 f3 f4 f5 + */ +static void modelasmMathPain3(void) +{ + f32 f6 = f1 * f5; + f32 f7 = f0 * f5; + f32 f8 = f1 * f4; + f32 f9 = f0 * f4; + + f12 = f2 * f4; + f13 = f2 * f5; + f14 = -f3; + + f15 = f8 * f3 - f7; + f16 = f6 * f3 + f9; + f17 = f1 * f2; + + f18 = f9 * f3 + f6; + f19 = f7 * f3 - f8; + f20 = f0 * f2; +} + +/** + * Expects: f0 f1 f2 f3 + */ +static void modelasmMathPain4(void) +{ + f32 f6; + f32 f7; + f32 f8; + f32 f9; + f32 f10; + f32 f11; + f32 f24; + f32 f25; + f32 f26; + f32 f27; + f32 f28; + + f4 = f0 * f0; + f5 = f1 * f1; + f6 = f2 * f2; + f4 = f4 + f5; + f5 = f3 * f3; + f4 = f4 + f6; + f4 = f4 + f5; + f4 = 2.0f / f4; + f5 = f1 * f4; + f6 = f2 * f4; + f7 = f3 * f4; + f8 = f0 * f5; + f9 = f0 * f6; + f10 = f0 * f7; + f11 = f1 * f5; + f24 = f1 * f6; + f16 = 1.0f - f11; + f25 = f1 * f7; + f20 = 1.0f - f11; + f26 = f2 * f6; + f13 = f24 + f10; + f27 = f2 * f7; + f12 = 1.0f - f26; + f28 = f3 * f7; + f14 = f25 - f9; + f12 = f12 - f28; + f15 = f24 - f10; + f16 = f16 - f28; + f17 = f27 + f8; + f18 = f25 + f9; + f19 = f27 - f8; + f20 = f20 - f26; +} + +/** + * Expects: f12-f23 + */ +static void modelasmMtxMultiply(Mtxf *src, Mtxf *dst) +{ + f32 f0; + f32 f1; + f32 f2; + f32 f3; + f32 f4; + f32 f5; + f32 f6; + f32 f7; + f32 f8; + f32 f9; + f32 f10; + s32 i; + + for (i = 0; i < 3; i++) { + f0 = src->m[0][i]; + f1 = src->m[1][i]; + f2 = src->m[2][i]; + f3 = src->m[3][i]; + + f4 = f0 * f12; + f5 = f1 * f13; + f6 = f2 * f14; + + dst->m[0][i] = f4 + f5 + f6; + + f8 = f0 * f15; + f9 = f1 * f16; + f10 = f2 * f17; + + dst->m[1][i] = f8 + f9 + f10; + + f4 = f0 * f18; + f5 = f1 * f19; + f6 = f2 * f20; + + dst->m[2][i] = f4 + f5 + f6; + + f8 = f0 * f21; + f9 = f1 * f22; + f10 = f2 * f23; + + dst->m[3][i] = f8 + f9 + f10 + f3; + } + + dst->m[0][3] = 0; + dst->m[1][3] = 0; + dst->m[2][3] = 0; + dst->m[3][3] = 1; +} + +static Mtxf *modelasmFindNodeMtx(struct model *model, struct modelnode *node) +{ + do { + u8 type = node->type & 0xff; + + if (type == MODELNODETYPE_CHRINFO) { + return &model->matrices[node->rodata->chrinfo.mtxindex]; + } + + if (type == MODELNODETYPE_POSITION) { + return &model->matrices[node->rodata->position.mtxindex0]; + } + + if (type == MODELNODETYPE_POSITIONHELD) { + return &model->matrices[node->rodata->positionheld.mtxindex]; + } + + node = node->parent; + } while (node); + + return NULL; +} + +/** + * See similar function func0f096890. + */ +static f32 modelasmAcosOrAsin(f32 f6) +{ + s32 t2; + s32 t3; + u16 *array; + s32 shiftamount; + s32 mask; + s32 s0; + s32 s1; + s32 s2; + s32 s3; + s32 s4; + + t2 = f6 * 32767.0f; + + if (t2 > 32767) { + t2 = 32767; + } else if (t2 < -32767) { + t2 = -32767; + } + + t3 = t2; + + if (t3 < 0) { + t3 = -t3; + } + + if (t3 >= 32736) { + array = &var8006ae90[126]; + t3 -= 32736; + shiftamount = 3; + mask = 0x07; + } else if (t3 >= 30720) { + array = &var8006ae90[62]; + t3 -= 30720; + shiftamount = 5; + mask = 0x1f; + } else { + array = &var8006ae90[0]; + shiftamount = 9; + mask = 0x1ff; + } + + s0 = t3 >> shiftamount; + array += s0; + s1 = array[0]; + s2 = array[1]; + s3 = s1 - s2; + s4 = t3 & mask; + s3 *= s4; + s3 >>= shiftamount; + t3 = s1 - s3; + + if (t2 < 0) { + t3 = 0xffff - t3; + } + + return 0.000047937632189132f * t3; +} + +f32 cosf(f32 radians) +{ + return sinf(radians + 1.570796251297f); +} + +f32 sinf(f32 radians) +{ + f32 f0; + f32 f13; + f32 f14; + f32 f15; + s32 t0; + s32 t1; + f32 ret; + + t0 = *(u32 *) &radians; + t0 = (t0 >> 22) & 0x1ff; + + if (t0 < 255) { + if (t0 >= 230) { + f14 = radians * radians; + + ret = 0.0000026057805371238f; + ret *= f14; + ret += -0.0001980960223591f; + ret *= f14; + ret += 0.0083330664783716f; + ret *= f14; + ret += -0.16666659712791f; + ret *= f14; + ret *= radians; + ret += radians; + } else { + ret = radians; + } + } else { + if (t0 < 310) { + f14 = radians * 0.31830987334251f; + + t1 = (s32) (f14 + 0.5f); + f14 = t1; + + f15 = M_PI; + f15 *= f14; + radians -= f15; + + f15 = 0.000000031786509424592f; + f15 *= f14; + radians -= f15; + + f14 = radians * radians; + + ret = 0.0000026057805371238f; + ret *= f14; + ret += -0.0001980960223591f; + ret *= f14; + ret += 0.0083330664783716f; + ret *= f14; + ret += -0.16666659712791f; + ret *= f14; + ret *= radians; + ret += radians; + + if (t1 & 1) { + ret = -ret; + } + } else { + ret = 0; + } + } + + return ret; +}