From 9b153e12a0700ec76277e5935fd2958709b1db6e Mon Sep 17 00:00:00 2001 From: Mark Langen Date: Sun, 29 Nov 2020 01:26:33 -0800 Subject: [PATCH] xMovePoint.cpp 60% complete * 100% match: xMovePointLoad, xMovePointSave, xMovePointReset, xMovePointSetup, xMovePointSplineDestroy. * 95% match: xMovePointGetNext, function is a 100% match save instruction ordering. * Did not attempt: xVec3Hdng and xMovePointSplineSetup, too much floating point math, need to do some easier float math functions first. --- asm/Core/x/xMovePoint.s | 45 +++++++----- src/Core/x/xMovePoint.cpp | 141 ++++++++++++++++++++++++++++++++++++-- src/Core/x/xMovePoint.h | 22 ++++++ src/Core/x/xScene.h | 64 ++++++++--------- 4 files changed, 218 insertions(+), 54 deletions(-) diff --git a/asm/Core/x/xMovePoint.s b/asm/Core/x/xMovePoint.s index 77debb0fd..ca2d7e5b9 100644 --- a/asm/Core/x/xMovePoint.s +++ b/asm/Core/x/xMovePoint.s @@ -172,9 +172,9 @@ lbl_800356D0: /* 800356D0 000324D0 80 9D 00 14 */ lwz r4, 0x14(r29) /* 800356D4 000324D4 38 61 00 2C */ addi r3, r1, 0x2c /* 800356D8 000324D8 80 BF 00 14 */ lwz r5, 0x14(r31) -/* 800356DC 000324DC C0 A2 85 54 */ lfs f5, lbl_803CCED4-_SDA2_BASE_(r2) +/* 800356DC 000324DC C0 A2 85 54 */ lfs f5, xMovePoint_float_twothirds-_SDA2_BASE_(r2) /* 800356E0 000324E0 C0 84 00 00 */ lfs f4, 0(r4) -/* 800356E4 000324E4 C0 C2 85 50 */ lfs f6, lbl_803CCED0-_SDA2_BASE_(r2) +/* 800356E4 000324E4 C0 C2 85 50 */ lfs f6, xMovePoint_float_onethird-_SDA2_BASE_(r2) /* 800356E8 000324E8 EC 05 01 32 */ fmuls f0, f5, f4 /* 800356EC 000324EC C0 25 00 00 */ lfs f1, 0(r5) /* 800356F0 000324F0 EC 06 00 7A */ fmadds f0, f6, f1, f0 @@ -245,11 +245,12 @@ xMovePointGetNext__FPC10xMovePointPC10xMovePointPP10xMovePointP5xVec3: /* 800357D4 000325D4 7C BD 2B 78 */ mr r29, r5 /* 800357D8 000325D8 7C DE 33 78 */ mr r30, r6 /* 800357DC 000325DC A0 03 00 1A */ lhz r0, 0x1a(r3) + /* 800357E0 000325E0 28 00 00 01 */ cmplwi r0, 1 /* 800357E4 000325E4 40 80 00 14 */ bge lbl_800357F8 /* 800357E8 000325E8 38 00 00 00 */ li r0, 0 /* 800357EC 000325EC 90 1D 00 00 */ stw r0, 0(r29) -/* 800357F0 000325F0 C0 22 85 58 */ lfs f1, lbl_803CCED8-_SDA2_BASE_(r2) +/* 800357F0 000325F0 C0 22 85 58 */ lfs f1, xMovePoint_float_0-_SDA2_BASE_(r2) /* 800357F4 000325F4 48 00 00 DC */ b lbl_800358D0 lbl_800357F8: /* 800357F8 000325F8 3B E0 00 00 */ li r31, 0 @@ -302,7 +303,7 @@ lbl_80035888: /* 8003589C 0003269C 93 FD 00 00 */ stw r31, 0(r29) /* 800358A0 000326A0 48 00 00 0C */ b lbl_800358AC lbl_800358A4: -/* 800358A4 000326A4 C0 22 85 58 */ lfs f1, lbl_803CCED8-_SDA2_BASE_(r2) +/* 800358A4 000326A4 C0 22 85 58 */ lfs f1, xMovePoint_float_0-_SDA2_BASE_(r2) /* 800358A8 000326A8 48 00 00 28 */ b lbl_800358D0 lbl_800358AC: /* 800358AC 000326AC 28 1E 00 00 */ cmplwi r30, 0 @@ -314,7 +315,7 @@ lbl_800358AC: /* 800358C4 000326C4 48 00 00 29 */ bl xVec3Hdng__FP5xVec3PC5xVec3PC5xVec3 /* 800358C8 000326C8 48 00 00 08 */ b lbl_800358D0 lbl_800358CC: -/* 800358CC 000326CC C0 22 85 58 */ lfs f1, lbl_803CCED8-_SDA2_BASE_(r2) +/* 800358CC 000326CC C0 22 85 58 */ lfs f1, xMovePoint_float_0-_SDA2_BASE_(r2) lbl_800358D0: /* 800358D0 000326D0 BB 61 00 0C */ lmw r27, 0xc(r1) /* 800358D4 000326D4 80 01 00 24 */ lwz r0, 0x24(r1) @@ -350,7 +351,7 @@ xVec3Hdng__FP5xVec3PC5xVec3PC5xVec3: /* 80035934 00032734 C0 04 00 08 */ lfs f0, 8(r4) /* 80035938 00032738 EC 3F 07 F2 */ fmuls f1, f31, f31 /* 8003593C 0003273C EF A2 00 28 */ fsubs f29, f2, f0 -/* 80035940 00032740 C0 02 85 5C */ lfs f0, lbl_803CCEDC-_SDA2_BASE_(r2) +/* 80035940 00032740 C0 02 85 5C */ lfs f0, xMovePoint_float_0p35-_SDA2_BASE_(r2) /* 80035944 00032744 C0 42 85 60 */ lfs f2, lbl_803CCEE0-_SDA2_BASE_(r2) /* 80035948 00032748 EC 3E 0F BA */ fmadds f1, f30, f30, f1 /* 8003594C 0003274C EC 3D 0F 7A */ fmadds f1, f29, f29, f1 @@ -363,7 +364,7 @@ xVec3Hdng__FP5xVec3PC5xVec3PC5xVec3: /* 80035968 00032768 D3 DF 00 00 */ stfs f30, 0(r31) /* 8003596C 0003276C D3 FF 00 04 */ stfs f31, 4(r31) /* 80035970 00032770 D3 BF 00 08 */ stfs f29, 8(r31) -/* 80035974 00032774 C0 22 85 5C */ lfs f1, lbl_803CCEDC-_SDA2_BASE_(r2) +/* 80035974 00032774 C0 22 85 5C */ lfs f1, xMovePoint_float_0p35-_SDA2_BASE_(r2) /* 80035978 00032778 48 00 00 5C */ b lbl_800359D4 lbl_8003597C: /* 8003597C 0003277C FC 00 0A 10 */ fabs f0, f1 @@ -371,17 +372,17 @@ lbl_8003597C: /* 80035984 00032784 FC 00 10 40 */ fcmpo cr0, f0, f2 /* 80035988 00032788 4C 40 13 82 */ cror 2, 0, 2 /* 8003598C 0003278C 40 82 00 24 */ bne lbl_800359B0 -/* 80035990 00032790 C0 02 85 58 */ lfs f0, lbl_803CCED8-_SDA2_BASE_(r2) +/* 80035990 00032790 C0 02 85 58 */ lfs f0, xMovePoint_float_0-_SDA2_BASE_(r2) /* 80035994 00032794 D0 1F 00 00 */ stfs f0, 0(r31) -/* 80035998 00032798 C0 02 85 5C */ lfs f0, lbl_803CCEDC-_SDA2_BASE_(r2) +/* 80035998 00032798 C0 02 85 5C */ lfs f0, xMovePoint_float_0p35-_SDA2_BASE_(r2) /* 8003599C 0003279C D0 1F 00 04 */ stfs f0, 4(r31) -/* 800359A0 000327A0 C0 02 85 58 */ lfs f0, lbl_803CCED8-_SDA2_BASE_(r2) +/* 800359A0 000327A0 C0 02 85 58 */ lfs f0, xMovePoint_float_0-_SDA2_BASE_(r2) /* 800359A4 000327A4 D0 1F 00 08 */ stfs f0, 8(r31) -/* 800359A8 000327A8 C0 22 85 58 */ lfs f1, lbl_803CCED8-_SDA2_BASE_(r2) +/* 800359A8 000327A8 C0 22 85 58 */ lfs f1, xMovePoint_float_0-_SDA2_BASE_(r2) /* 800359AC 000327AC 48 00 00 28 */ b lbl_800359D4 lbl_800359B0: /* 800359B0 000327B0 4B FD 4E 4D */ bl xsqrt__Ff -/* 800359B4 000327B4 C0 02 85 5C */ lfs f0, lbl_803CCEDC-_SDA2_BASE_(r2) +/* 800359B4 000327B4 C0 02 85 5C */ lfs f0, xMovePoint_float_0p35-_SDA2_BASE_(r2) /* 800359B8 000327B8 EC 00 08 24 */ fdivs f0, f0, f1 /* 800359BC 000327BC EC 7E 00 32 */ fmuls f3, f30, f0 /* 800359C0 000327C0 EC 5F 00 32 */ fmuls f2, f31, f0 @@ -405,13 +406,25 @@ lbl_800359D4: .endif .section .sdata2 -lbl_803CCED0: +/* = 0.333...f */ +.global xMovePoint_float_onethird +xMovePoint_float_onethird: .incbin "baserom.dol", 0x2B6770, 0x4 -lbl_803CCED4: + +/* = 0.666...f */ +.global xMovePoint_float_twothirds +xMovePoint_float_twothirds: .incbin "baserom.dol", 0x2B6774, 0x4 -lbl_803CCED8: + +/* = 0.0f */ +.global xMovePoint_float_0 +xMovePoint_float_0: .incbin "baserom.dol", 0x2B6778, 0x4 -lbl_803CCEDC: + +/* = 0.35f */ +.global xMovePoint_float_0p35 +xMovePoint_float_0p35: .incbin "baserom.dol", 0x2B677C, 0x4 + lbl_803CCEE0: .incbin "baserom.dol", 0x2B6780, 0x8 diff --git a/src/Core/x/xMovePoint.cpp b/src/Core/x/xMovePoint.cpp index 5c536b7dc..fe1dcb445 100644 --- a/src/Core/x/xMovePoint.cpp +++ b/src/Core/x/xMovePoint.cpp @@ -2,32 +2,159 @@ #include +#include "xMath.h" +#include "xScene.h" +#include "xMemMgr.h" + +float32 xVec3Hdng(xVec3* a, const xVec3* b, const xVec3* c); + // func_80035494 -#pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointInit__FP10xMovePointP15xMovePointAsset") +void xMovePointInit(xMovePoint* ent, xMovePointAsset* asset) +{ + xBaseInit(ent, asset); + ent->asset = asset; + + // They didn't use `&asset->pos` here as that doesn't generate a 100% match. + ent->pos = &ent->asset->pos; + ent->on = asset->on; + ent->delay = asset->delay; + ent->spl = NULL; + + if (asset->numPoints != 0) + { + ent->nodes = (xMovePoint**)xMemAlloc(asset->numPoints * sizeof(xMovePoint*)); + } + else + { + ent->nodes = NULL; + } +} // func_8003551C -#pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointSave__FP10xMovePointP7xSerial") +void xMovePointSave(xMovePoint* ent, xSerial* s) +{ + xBaseSave(ent, s); +} // func_8003553C -#pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointLoad__FP10xMovePointP7xSerial") +void xMovePointLoad(xMovePoint* ent, xSerial* s) +{ + xBaseLoad(ent, s); +} // func_8003555C -#pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointReset__FP10xMovePoint") +void xMovePointReset(xMovePoint* m) +{ + xBaseReset(m, m->asset); + + m->on = m->asset->on; + m->delay = m->asset->delay; +} // func_800355A4 -#pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointSetup__FP10xMovePointP6xScene") +void xMovePointSetup(xMovePoint* m, xScene* sc) +{ + m->node_wt_sum = 0; + uint32* pointIds = (uint32*)(m->asset + 1); + for (uint16 idx = 0; idx < m->asset->numPoints; ++idx) + { + uint32 id = pointIds[idx]; + m->nodes[idx] = (xMovePoint*)xSceneResolvID(sc, id); + m->node_wt_sum += m->nodes[idx]->asset->wt; + m->nodes[idx]->prev = m; + } +} // func_80035640 #pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointSplineSetup__FP10xMovePoint") // func_800357A0 -#pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointSplineDestroy__FP10xMovePoint") +void xMovePointSplineDestroy(xMovePoint* m) +{ + if (m->spl != NULL) + { + m->spl = NULL; + } +} // func_800357B8 +#if 1 #pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointGetNext__FPC10xMovePointPC10xMovePointPP10xMovePointP5xVec3") +#else +// If you uncomment the numPoints variable then this function is a perfect match +// minus ordering. In the original assembly some variable fetches are lifted to +// places earlier in the assembly listing than what this comiles to for some +// reason. +// The r27-30 registers used to hold the main varibles of the function are all +// perfect matches with this code. +extern float xMovePoint_float_0; +float32 xMovePointGetNext(xMovePoint* m, xMovePoint* prev, xMovePoint** next, xVec3* hdng) +{ + if (m->asset->numPoints < 1) + { + *next = NULL; + return xMovePoint_float_0; + } + + xMovePoint* previousOption = NULL; + + int32 rnd = xrand() % m->node_wt_sum; + + // The debug symbols don't show a dedicated numPoints var, but if it isn't + // present, then getting numPoints isn't lifted outside of the loop, which + // it is in the original assembly. + //uint16 numPoints = m->asset->numPoints; + + for (uint16 idx = 0; idx < m->asset->numPoints; ++idx) + { + *next = m->nodes[idx]; + rnd -= (*next)->asset->wt; + if ((*next)->on == 0) + { + *next = NULL; + } + else + { + previousOption = *next; + if (*next == prev) + { + *next = NULL; + } + else if (rnd < 0) + { + break; + } + } + } + + if (*next == NULL) + { + if (previousOption != NULL) + { + *next = previousOption; + } + else + { + return xMovePoint_float_0; + } + } + + if (hdng) + { + return xVec3Hdng(hdng, m->pos, (*next)->pos); + } + else + { + return xMovePoint_float_0; + } +} +#endif // func_800358E4 -#pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xMovePointGetPos__FPC10xMovePoint") +xVec3* xMovePointGetPos(xMovePoint* m) +{ + return m->pos; +} // func_800358EC #pragma GLOBAL_ASM("asm/Core/x/xMovePoint.s", "xVec3Hdng__FP5xVec3PC5xVec3PC5xVec3") diff --git a/src/Core/x/xMovePoint.h b/src/Core/x/xMovePoint.h index b36772185..2cfbf1c2f 100644 --- a/src/Core/x/xMovePoint.h +++ b/src/Core/x/xMovePoint.h @@ -5,15 +5,21 @@ #include "xMath3.h" #include "xSpline.h" +struct xScene; + struct xMovePointAsset : xBaseAsset { xVec3 pos; uint16 wt; + + // Offset: 0x16 uint8 on; uint8 bezIndex; uint8 flg_props; uint8 pad; uint16 numPoints; + + // Offset: 0x1C float32 delay; float32 zoneRadius; float32 arenaRadius; @@ -22,14 +28,30 @@ struct xMovePointAsset : xBaseAsset struct xMovePoint : xBase { xMovePointAsset* asset; + + // Offset: 0x14 xVec3* pos; xMovePoint** nodes; xMovePoint* prev; uint32 node_wt_sum; + + // Offset: 0x24 uint8 on; uint8 pad[2]; + + // Offset: 0x28 float32 delay; xSpline3* spl; }; +xVec3* xMovePointGetPos(xMovePoint* m); +float32 xMovePointGetNext(xMovePoint* m, xMovePoint* prev, xMovePoint** next, xVec3* hdng); +void xMovePointSplineDestroy(xMovePoint* m); +void xMovePointSplineSetup(xMovePoint* m); +void xMovePointSetup(xMovePoint* m, xScene* sc); +void xMovePointReset(xMovePoint* m); +void xMovePointLoad(xMovePoint* ent, xSerial* s); +void xMovePointSave(xMovePoint* ent, xSerial* s); +void xMovePointInit(xMovePoint* m, xMovePointAsset* asset); + #endif \ No newline at end of file diff --git a/src/Core/x/xScene.h b/src/Core/x/xScene.h index 36e277f74..52f54cf84 100644 --- a/src/Core/x/xScene.h +++ b/src/Core/x/xScene.h @@ -6,40 +6,42 @@ #include "xEnv.h" #include "xMemMgr.h" -typedef char*(*xSceneBase2NameCallback)(xBase*); -typedef char*(*xSceneID2NameCallback)(uint32); -typedef xBase*(*xSceneResolvIDCallback)(uint32); +typedef char* (*xSceneBase2NameCallback)(xBase*); +typedef char* (*xSceneID2NameCallback)(uint32); +typedef xBase* (*xSceneResolvIDCallback)(uint32); struct xScene { - uint32 sceneID; - uint16 flags; - uint16 num_ents; - uint16 num_trigs; - uint16 num_stats; - uint16 num_dyns; - uint16 num_npcs; - uint16 num_act_ents; - uint16 num_nact_ents; - float32 gravity; - float32 drag; - float32 friction; - uint16 num_ents_allocd; - uint16 num_trigs_allocd; - uint16 num_stats_allocd; - uint16 num_dyns_allocd; - uint16 num_npcs_allocd; - xEnt** trigs; - xEnt** stats; - xEnt** dyns; - xEnt** npcs; - xEnt** act_ents; - xEnt** nact_ents; - xEnv* env; - xMemPool mempool; - xSceneResolvIDCallback resolvID; - xSceneBase2NameCallback base2Name; - xSceneID2NameCallback id2Name; + uint32 sceneID; + uint16 flags; + uint16 num_ents; + uint16 num_trigs; + uint16 num_stats; + uint16 num_dyns; + uint16 num_npcs; + uint16 num_act_ents; + uint16 num_nact_ents; + float32 gravity; + float32 drag; + float32 friction; + uint16 num_ents_allocd; + uint16 num_trigs_allocd; + uint16 num_stats_allocd; + uint16 num_dyns_allocd; + uint16 num_npcs_allocd; + xEnt** trigs; + xEnt** stats; + xEnt** dyns; + xEnt** npcs; + xEnt** act_ents; + xEnt** nact_ents; + xEnv* env; + xMemPool mempool; + xSceneResolvIDCallback resolvID; + xSceneBase2NameCallback base2Name; + xSceneID2NameCallback id2Name; }; +xBase* xSceneResolvID(xScene* sc, uint32 id); + #endif \ No newline at end of file