Alchemy
Loading...
Searching...
No Matches

math.c

Go to the documentation of this file.
1/// @file
2/// Random numbers, angles and square roots.
3/// Part of runtime.c, the runtime object, compiled only through it.
4
6
7/// Advances the game's random number generator (the C library's classic
8/// linear congruential one), stores the new seed and returns 16 bits of it.
9/// Called throughout the game.
11 enum { MULTIPLIER = 0x41c64e6d, INCREMENT = 0x3039 };
12 u32 value = gRandomSeed * MULTIPLIER + INCREMENT;
13
14 gRandomSeed = value;
15 return (value << 8) >> 16;
16}
17
18/// Moves the point `position` by `radius` in direction `angle` on the ground
19/// plane: x by the cosine, z by the sine. The point is any three s32
20/// coordinates x, y, z in a row (struct FieldPosition, struct EffectVector and
21/// others), so it takes a plain pointer. Byte offsets reach each coordinate
22/// without treating separate struct members as an array.
23void Vector_AddPolarOffset(s32 radius, s32 angle, void *position) {
24 u8 *coordinate = position;
25
26 *(s32 *)coordinate += Iwram_MulQ16(radius, Trig_Sin(angle + 0x4000));
27 // Step across y separately; merging the steps changes native writeback.
28 coordinate += sizeof(s32);
29 coordinate += sizeof(s32);
30 *(s32 *)coordinate += Iwram_MulQ16(radius, Trig_Sin(angle));
31}
32
33/// Returns the angle of the vector (x, y), in 1/65536 turns, measured from
34/// the y axis: 0 along +y, 0x4000 along +x. It binary-searches the tangent
35/// table to 1/256 of a quarter turn.
37 const u16 *table;
38 s32 value;
39 s32 ratio;
40 s32 result;
41
42 // Handle axes without dividing by zero; the quadrant correction below
43 // supplies the half-turn for a vector along -y.
44 if (x == 0) {
45 result = 0;
46 } else if (y == 0) {
47 result = 0x4000;
48 } else {
49 // Search only the first quadrant, with |x| / |y| in 8.8 fixed point.
50 ratio = y;
51 if (ratio < 0)
52 ratio = -ratio;
53 value = x;
54 if (value < 0)
55 value = -value;
56
57 ratio = (value << 8) / ratio;
58 // Beyond entry 255's tangent, use the quarter-turn limit instead of
59 // the largest angle the eight search bits can represent.
60 result = 0x4000;
61 if (ratio <= 0xFB6A) {
62 // Eight comparisons choose angle bits 0x2000 down to 0x40. Halving
63 // each table step retains the interval selected by the earlier bits.
64 table = &gMath_TanTable[127];
65 result = 0;
66
67 value = *table;
68 table -= 0x40;
69 if (ratio > value) {
70 result = 0x2000;
71 table += 0x80;
72 }
73 value = *table;
74 table -= 0x20;
75 if (ratio > value) {
76 result |= 0x1000;
77 table += 0x40;
78 }
79 value = *table;
80 table -= 0x10;
81 if (ratio > value) {
82 result |= 0x800;
83 table += 0x20;
84 }
85 value = *table;
86 table -= 8;
87 if (ratio > value) {
88 result |= 0x400;
89 table += 0x10;
90 }
91 value = *table;
92 table -= 4;
93 if (ratio > value) {
94 result |= 0x200;
95 table += 8;
96 }
97 value = *table;
98 table -= 2;
99 if (ratio > value) {
100 result |= 0x100;
101 table += 4;
102 }
103 value = *table;
104 table--;
105 if (ratio > value) {
106 result |= 0x80;
107 table += 2;
108 }
109 value = *table;
110 if (ratio > value)
111 result |= 0x40;
112 }
113 }
114
115 // Restore the signs after searching magnitudes alone.
116 if (y < 0)
117 result = 0x8000 - result;
118 if (x < 0)
119 result = -result;
120
121 return (u16)result;
122}
123
124/// Returns the integer square root of `value`, a bit at a time. Reached
125/// through the far-call table.
127 s32 trial;
128 s32 remainder;
129 s32 bit;
130 s32 result;
131
132 // remainder is value - result squared. Each trial is the extra square
133 // cost of setting the next bit, preserving the higher bits already chosen.
134 remainder = value;
135 result = 0;
136 bit = 0xf;
137 do {
138 trial = (result << (bit + 1)) + (1 << (bit * 2));
139 if (trial <= remainder) {
140 result |= 1 << bit;
141 remainder -= trial;
142 }
143 bit -= 1;
144 } while (bit >= 0);
145 return result;
146}
147
148/// Square root of a 16.16 fixed-point value, in 16.16.
149s32 FixedSqrt(s32 value) { return Iwram_Sqrt(value) << 8; }
150
u32 gRandomSeed
s32 Trig_Sin(s32 angle)
static s32 Iwram_Sqrt(s32 value)
Definition iwram_call.h:63
#define Iwram_MulQ16(left, right)
Definition iwram_call.h:127
s32 Math_IntegerSqrt(s32 value)
Returns the integer square root of value, a bit at a time.
Definition math.c:126
void Vector_AddPolarOffset(s32 radius, s32 angle, void *position)
Moves the point position by radius in direction angle on the ground plane: x by the cosine,...
Definition math.c:23
u32 Random16(void)
Advances the game's random number generator (the C library's classic linear congruential one),...
Definition math.c:10
s32 ArcTan2(s32 x, s32 y)
Returns the angle of the vector (x, y), in 1/65536 turns, measured from the y axis: 0 along +y,...
Definition math.c:36
s32 Palette_GetBasicObjColors(void)
Definition math.c:151
s32 FixedSqrt(s32 value)
Square root of a 16.16 fixed-point value, in 16.16.
Definition math.c:149
const u16 gMath_TanTable[258]
Tangents scaled by 256: index i is tan(i * 45 / 128 degrees), so index 128 is tan(45 degrees).
Definition math_table.c:55
What every part of the runtime object shares: its includes and the library call two parts make.
const u8 gSystem_BasicColorPalette[]
signed int s32
Definition types.h:14
unsigned int u32
Definition types.h:15
unsigned short u16
Definition types.h:13
unsigned char u8
Definition types.h:11