Skip to content

Commit 2cfeaa1

Browse files
[COLL] Barycentric Test function decompiled (#229)
* first function in coll decompiled * better macro * COLL_BarycentricTest decompiled * dont generate code if profiler guard isn't active * fix gamma calculation * flush cache after modifying instructions * add in naughty dog bug... * address PR review
1 parent 97640c5 commit 2cfeaa1

File tree

14 files changed

+281
-24
lines changed

14 files changed

+281
-24
lines changed

include/ctr/coll.h

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,45 @@
11
#pragma once
22

3+
#include <ctr/macros.h>
34
#include <ctr/math.h>
5+
#include <ctr/lev.h>
46

5-
void COLL_ProjectPointToEdge(SVec3* out, const SVec3* v1, const SVec3* v2, const SVec3* point);
7+
typedef enum Axis
8+
{
9+
AXIS_Z = 1,
10+
AXIS_X = 2,
11+
AXIS_Y = 3,
12+
} Axis;
13+
14+
typedef enum BarycentricTest
15+
{
16+
BARYCENTRIC_TEST_INVALID = -1,
17+
BARYCENTRIC_TEST_SNAP_V1 = 0,
18+
BARYCENTRIC_TEST_EDGE_V1_V2 = 1,
19+
BARYCENTRIC_TEST_SNAP_V2 = 2,
20+
BARYCENTRIC_TEST_EDGE_V2_V3 = 3,
21+
BARYCENTRIC_TEST_SNAP_V3 = 4,
22+
BARYCENTRIC_TEST_EDGE_V1_V3 = 5,
23+
BARYCENTRIC_TEST_INSIDE_TRIANGLE = 6,
24+
} BarycentricTest;
25+
26+
typedef struct CollVertex
27+
{
28+
SVec3 pos;
29+
u16 normalDominantAxis;
30+
Vertex* levVertex;
31+
SVec3 triNormal;
32+
u16 planeDist;
33+
} CollVertex;
34+
35+
typedef struct TestVertex
36+
{
37+
SVec3 pos;
38+
u16 normalDominantAxis;
39+
SVec3 triNormal;
40+
u16 planeDist;
41+
SVec3 interpolationPoint;
42+
} TestVertex;
43+
44+
void COLL_ProjectPointToEdge(SVec3* out, const SVec3* v1, const SVec3* v2, const SVec3* point);
45+
s32 COLL_BarycentricTest(TestVertex* t, const CollVertex* v1, const CollVertex* v2, const CollVertex* v3);

include/ctr/lev.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <ctr/macros.h>
4+
#include <ctr/math.h>
5+
6+
typedef union Color
7+
{
8+
struct
9+
{
10+
u8 r;
11+
u8 g;
12+
u8 b;
13+
u8 a;
14+
};
15+
u32 color;
16+
} Color;
17+
18+
typedef struct Vertex
19+
{
20+
SVec3 pos;
21+
u16 flags;
22+
Color colorHi;
23+
Color colorLo;
24+
} Vertex;

include/ctr/macros.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ typedef int8_t s8;
4646
#define OFFSETOF(TYPE, ELEMENT) ((unsigned int)&(((TYPE *)0)->ELEMENT))
4747

4848
#define nullptr ((void *) 0)
49-
#define force_inline static inline __attribute__((always_inline))
49+
#define force_inline static inline __attribute__((always_inline))
50+
51+
//#define FIX_CTR_BUGS

include/ctr/nd.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <ctr/macros.h>
44
#include <ctr/math.h>
55
#include <ctr/rng.h>
6+
#include <ctr/coll.h>
67

78
void ND_LOAD_XnfFile(char* filename, u32 address, char* dummy);
89
s32 ND_SquareRoot0_stub(s32 n);
@@ -27,4 +28,5 @@ u16 ND_RNG_PseudoRand(u16 n);
2728
u32 ND_RNG_Random(RNGSeed* seed);
2829

2930
/* COLL */
30-
void ND_COLL_ProjectPointToEdge(SVec3* out, const SVec3* v1, const SVec3* v2, const SVec3* point);
31+
void ND_COLL_ProjectPointToEdge(SVec3* out, const SVec3* v1, const SVec3* v2, const SVec3* point);
32+
s32 ND_COLL_BarycentricTest(TestVertex* t, const CollVertex* v1, const CollVertex* v2, const CollVertex* v3);

include/ctr/profiler.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#pragma once
22

3-
#define REWRITE_PROFILER
4-
void LoadProfilerPatches();
3+
//#define REWRITE_PROFILER
4+
5+
void LoadProfilerPatches();

include/ctr/test.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,18 @@ void PatchFunction_End(u32 index);
1414
u32 PrintSVectorDiff(const char* name, const SVec3* expected, const SVec3* ret);
1515
u32 PrintMatrixDiff(const char* name, const Matrix* expected, const Matrix* ret, u32 cmpTrans);
1616

17+
force_inline void FlushCache()
18+
{
19+
register int n asm("t1") = 0x44;
20+
__asm__ volatile("" : "=r"(n) : "r"(n));
21+
((void (*)())0xa0)();
22+
}
23+
1724
#define BACKUP_ADDR 0x80400000
1825

19-
//#define TEST_MATH_IMPL
20-
//#define TEST_RNG_IMPL
21-
//#define TEST_COLL_IMPL
26+
#define TEST_MATH_IMPL
27+
#define TEST_RNG_IMPL
28+
#define TEST_COLL_IMPL
2229

2330
#ifdef TEST_MATH_IMPL
2431
void TEST_MATH_Sin(u32 angle, s32 ret);
@@ -58,6 +65,8 @@ u32 PrintMatrixDiff(const char* name, const Matrix* expected, const Matrix* ret,
5865

5966
#ifdef TEST_COLL_IMPL
6067
void TEST_COLL_ProjectPointToEdge(const SVec3* v1, const SVec3* v2, const SVec3* point, const SVec3* ret);
68+
void TEST_COLL_BarycentricTest(TestVertex* t, const CollVertex* v1, const CollVertex* v2, const CollVertex* v3, const SVec3* pos, s32 ret);
6169
#else
6270
#define TEST_COLL_ProjectPointToEdge(out, v1, v2, point)
71+
#define TEST_COLL_BarycentricTest(t, v1, v2, v3, pos, ret)
6372
#endif

rewrite/buildList.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ common, header, 0x8000B0B8, 0x0, src/hooks/dll/load_decomp.c
44

55
// decomp files
66
common, DLL, 0x80200000, 0x0, src/exe/*.c, DECOMP.BIN
7-
common, DLL, 0x80600000, 0x0, src/tests/*.c, TESTS.BIN
7+
common, DLL, 0x80600000, 0x0, src/tests/*.c src/tests/test_wrappers.s, TESTS.BIN
88

99
// profiler files
10-
common, DLL, 0x80500000, 0x0, src/profiler/*.c, PROFILER.BIN
10+
common, DLL, 0x80500000, 0x0, src/profiler/*.c, PROFILER.BIN

rewrite/src/exe/coll.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,119 @@ void COLL_ProjectPointToEdge(SVec3* out, const SVec3* v1, const SVec3* v2, const
3636
out->y = coords.y;
3737
out->z = coords.z;
3838
TEST_COLL_ProjectPointToEdge(v1, v2, point, out);
39+
}
40+
41+
/* Address: 0x8001f928 */
42+
static s32 _COLL_BarycentricTest(TestVertex* t, const CollVertex* v1, const CollVertex* v2, const CollVertex* v3)
43+
{
44+
Vec2 deltaT;
45+
Vec2 deltaTri[2];
46+
const SVec3* edgeV2;
47+
const SVec3* edgeV3;
48+
u32 firstAxis, secondAxis;
49+
50+
if (t->normalDominantAxis == AXIS_X)
51+
{
52+
firstAxis = 1; // y
53+
secondAxis = 2; // z
54+
}
55+
else if (t->normalDominantAxis == AXIS_Y)
56+
{
57+
firstAxis = 2; // z
58+
secondAxis = 0; // x
59+
}
60+
else
61+
{
62+
firstAxis = 0; // x
63+
secondAxis = 1; // y
64+
}
65+
66+
deltaTri[0].x = v2->pos.v[firstAxis] - v1->pos.v[firstAxis];
67+
deltaTri[0].y = v3->pos.v[firstAxis] - v1->pos.v[firstAxis];
68+
deltaT.x = t->interpolationPoint.v[firstAxis] - v1->pos.v[firstAxis];
69+
edgeV2 = &v2->pos;
70+
edgeV3 = &v3->pos;
71+
if (abs(deltaTri[0].x) < abs(deltaTri[0].y))
72+
{
73+
edgeV2 = &v3->pos;
74+
edgeV3 = &v2->pos;
75+
s32 temp = deltaTri[0].x;
76+
deltaTri[0].x = deltaTri[0].y;
77+
deltaTri[0].y = temp;
78+
}
79+
deltaTri[1].x = edgeV2->v[secondAxis] - v1->pos.v[secondAxis];
80+
deltaTri[1].y = edgeV3->v[secondAxis] - v1->pos.v[secondAxis];
81+
deltaT.y = t->interpolationPoint.v[secondAxis] - v1->pos.v[secondAxis];
82+
83+
s32 beta = FP(-1);
84+
s32 gamma = FP(-1);
85+
if (deltaTri[0].x != 0)
86+
{
87+
s32 dem = ((deltaTri[1].y * deltaTri[0].x) - (deltaTri[0].y * deltaTri[1].x)) >> 6;
88+
if (dem != 0)
89+
{
90+
beta = (((deltaT.y * deltaTri[0].x) - (deltaT.x * deltaTri[1].x)) << 6) / dem;
91+
gamma = ((deltaT.x * FP_ONE) - (beta * deltaTri[0].y)) / deltaTri[0].x;
92+
}
93+
}
94+
else
95+
{
96+
if ((deltaTri[0].y != 0) && (deltaTri[1].x != 0))
97+
{
98+
beta = FP_DIV(deltaT.y, deltaTri[0].y);
99+
gamma = ((deltaT.y * FP_ONE) - (beta * deltaTri[1].y)) / deltaTri[1].x;
100+
}
101+
}
102+
103+
/* Naughty Dog bug: their hand written assembly code
104+
forgets to check beta == -1, creating false collisions */
105+
#ifdef FIX_CTR_BUGS
106+
if ((beta == FP(-1)) || (gamma == FP(-1))) { return BARYCENTRIC_TEST_INVALID; }
107+
#else
108+
if (gamma == FP(-1)) { return BARYCENTRIC_TEST_INVALID; }
109+
#endif
110+
111+
s32 alpha = beta + gamma + FP(-1);
112+
if (gamma < 0)
113+
{
114+
if (beta < 0)
115+
{
116+
t->pos = v1->pos;
117+
return BARYCENTRIC_TEST_SNAP_V1;
118+
}
119+
if (alpha < 0)
120+
{
121+
COLL_ProjectPointToEdge(&t->pos, &v1->pos, edgeV3, &t->interpolationPoint);
122+
return BARYCENTRIC_TEST_EDGE_V1_V3;
123+
}
124+
t->pos = *edgeV3;
125+
return BARYCENTRIC_TEST_SNAP_V3;
126+
}
127+
if (beta < 0)
128+
{
129+
if (alpha < 0)
130+
{
131+
COLL_ProjectPointToEdge(&t->pos, &v1->pos, edgeV2, &t->interpolationPoint);
132+
return BARYCENTRIC_TEST_EDGE_V1_V2;
133+
}
134+
t->pos = *edgeV2;
135+
return BARYCENTRIC_TEST_SNAP_V2;
136+
}
137+
if (alpha > 0)
138+
{
139+
COLL_ProjectPointToEdge(&t->pos, edgeV2, edgeV3, &t->interpolationPoint);
140+
return BARYCENTRIC_TEST_EDGE_V2_V3;
141+
}
142+
t->pos = t->interpolationPoint;
143+
return BARYCENTRIC_TEST_INSIDE_TRIANGLE;
144+
}
145+
146+
s32 COLL_BarycentricTest(TestVertex* t, const CollVertex* v1, const CollVertex* v2, const CollVertex* v3)
147+
{
148+
#ifdef TEST_COLL_IMPL
149+
TestVertex input = *t;
150+
#endif
151+
const s32 ret = _COLL_BarycentricTest(t, v1, v2, v3);
152+
TEST_COLL_BarycentricTest(&input, v1, v2, v3, &t->pos, ret);
153+
return ret;
39154
}

rewrite/src/profiler/benchmark.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// When running OG functions,
66
// dont forget to undefine these in ctr\test.h:
77
// TEST_MATH_IMPL, TEST_RNG_IMPL, TEST_COLL_IMPL
8+
#ifdef REWRITE_PROFILER
89

910
void RunBenchmark()
1011
{
@@ -30,5 +31,7 @@ void RunBenchmark()
3031
{
3132
ND_COLL_ProjectPointToEdge(&out, &v1, &v2, &point);
3233
}
33-
34-
}
34+
35+
}
36+
37+
#endif // REWRITE_PROFILER

rewrite/src/profiler/profiler.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#include <ctr/profiler.h>
22
#include <ctr/nd.h>
33

4+
#ifdef REWRITE_PROFILER
5+
46
// No Vehicle.h
57
struct MetaPhys
68
{
@@ -51,7 +53,7 @@ int Debug_GetPreciseTime()
5153
int sysClock =
5254
ND_GetRCnt(0xf2000001) +
5355
sdata->rcntTotalUnits;
54-
56+
5557
return sysClock;
5658
}
5759

@@ -65,42 +67,44 @@ void Hook_DrawOTag(int a)
6567
if (timeRed == 0)
6668
{
6769
timeStart = Debug_GetPreciseTime();
68-
70+
6971
void RunBenchmark();
7072
RunBenchmark();
71-
73+
7274
timeEnd = Debug_GetPreciseTime();
73-
75+
7476

7577
timeRed = timeEnd - timeStart;
7678
}
77-
79+
7880
struct GameTracker* gGT = sdata->gGT;
79-
81+
8082
if((gGT->gameMode1 & (LOADING|1)) == 0)
8183
{
8284
// reset depth to CLOSEST
8385
gGT->pushBuffer_UI.ptrOT =
8486
gGT->otSwapchainDB[gGT->swapchainIndex];
85-
86-
87+
88+
8789
#ifndef REBUILD_PC
8890
char* string = (char*)0x1f800000;
8991
#else
9092
char string[128];
9193
#endif
92-
94+
9395
ND_sprintf(string, "RED %d", timeRed);
9496
ND_DecalFont_DrawLine(string, 0x14, 0x5C, FONT_SMALL, 0);
9597
}
96-
98+
9799
ND_DrawOTag(a);
98100
}
99101

100102
#define JMP(dest) (((unsigned long)dest & 0x3FFFFFF) >> 2 | 0x8000000)
101103
#define JAL(dest) (((unsigned long)dest & 0x3FFFFFF) >> 2 | 0xC000000)
102104

103105
void LoadProfilerPatches()
104-
{
106+
{
105107
*(int*)0x800379b0 = JAL(Hook_DrawOTag);
106-
}
108+
}
109+
110+
#endif // REWRITE_PROFILER

0 commit comments

Comments
 (0)