pmd-red/src/math.c

326 lines
5.5 KiB
C

#include "global.h"
#include "globaldata.h"
#include "math.h"
#include "data/math.h"
u32 fast_mod_3(s32 x) {
if (x < 0x100) {
return gFastMod3Lookup[x];
}
return x % 3;
}
s32 sin_abs_4096(s32 x) {
switch (x & 0xc00) {
case 0x000:
return gFastSinLookup[x & 0x3ff];
case 0x400:
return gFastSinLookup[0x3ff - (x & 0x3ff)];
case 0x800:
return -gFastSinLookup[x & 0x3ff];
case 0xc00:
return -gFastSinLookup[0x3ff - (x & 0x3ff)];
}
return 0;
}
s32 cos_4096(s32 x) {
switch (x & 0xc00) {
case 0x000:
return gFastSinLookup[0x3ff - (x & 0x3ff)];
case 0x400:
return -gFastSinLookup[x & 0x3ff];
case 0x800:
return -gFastSinLookup[0x3ff - (x & 0x3ff)];
case 0xc00:
return gFastSinLookup[x & 0x3ff];
}
return 0;
}
bool8 u32_pair_less_than(u32 x_hi, u32 x_lo, u32 y_hi, u32 y_lo) {
if ((u32)x_hi < (u32)y_hi) {
return TRUE;
} else if ((u32)x_hi > (u32)y_hi) {
return FALSE;
} else if (x_lo >= y_lo) {
return FALSE;
} else {
return TRUE;
}
}
s24_8 s24_8_mul(s24_8 x, s24_8 y) {
s24_8 ret;
bool8 sgn0 = x < 0;
bool8 sgn1 = y < 0;
if (x == 0) {
return 0;
}
if (y == 0) {
return 0;
}
if (sgn0) {
x = -x;
}
if (sgn1) {
y = -y;
}
ret = u24_8_mul(x, y);
if (sgn0 != sgn1) {
ret = -ret;
}
return ret;
}
s24_8 s24_8_div(s24_8 x, s24_8 y) { // signed division
s24_8 ret;
bool8 sgn0 = x < 0;
bool8 sgn1 = y < 0;
if (y == 0) {
return INT32_MAX;
}
if (x == 0) {
return 0;
}
if (sgn0) {
x = -x;
}
if (sgn1) {
y = -y;
}
ret = u24_8_div(x, y);
if (sgn0 != sgn1) {
ret = -ret;
}
return ret;
}
u24_8 u24_8_mul(u24_8 x, u24_8 y) {
// We need 64 bits for intermediate steps of the multiplication.
u32 x_h, x_l;
u32 y_h, y_l;
u32 out_h, out_l;
s32 i;
u32 high_bit_mask;
u32 round_up;
if (x == 0 || y == 0) {
return 0;
}
x_h = 0;
x_l = x;
y_h = 0;
y_l = y;
out_h = 0;
out_l = 0;
high_bit_mask = 0x80 << 0x18; // high bit of u32
for (i = 0; i < 64; ++i) {
u32 prev_out_l = out_l;
u32 y_bit = 1;
y_bit &= y_l;
if (y_bit) {
out_l += x_l;
out_h += x_h;
if (prev_out_l > out_l) {
++out_h;
}
}
y_l >>= 1;
if (y_h & 1) {
y_l |= high_bit_mask;
}
y_h >>= 1;
x_h <<= 1;
if (x_l & high_bit_mask) {
x_h |= 1;
}
do {x_l <<= 1;} while(0); // wtf moment
}
round_up = (out_l >> 0x7) & 1;
out_l = (out_l >> 0x8) | (out_h << 0x18);
if (round_up) {
++out_l;
}
return out_l;
}
u24_8 u24_8_div(u24_8 x, u24_8 y)
{
bool8 bVar1;
u32 r9;
u32 r2;
u32 r4;
u32 r5;
u32 r6;
u32 r7;
u32 r8;
int counter;
s32 sl;
s32 flag;
s32 save;
if (y == 0) {
return 0x7fffffff;
}
else if (x == 0) {
return 0;
}
else {
r7 = x >> 0x18;
r6 = x << 8;
sl = y;
r9 = 0;
r5 = 0;
r4 = 0;
r2 = 0;
r8 = 1;
for(counter = 0x3f; counter >= 0; counter--)
{
r5 <<= 1;
if ((r4 & 0x80000000) != 0) {
r5 |= r8;
}
flag = -2;
r4 <<= 1;
if ((r7 & 0x80000000) != 0) {
r4 |= r8;
}
r7 <<= 1;
if ((r6 & 0x80000000) != 0) {
r7 |= r8;
}
r6 <<= 1;
r6 &= flag;
if (u32_pair_less_than(r5,r4,0,sl) == 0) {
save = r4;
bVar1 = 1;
r4 = r4 - sl;
r5 = r5 - r2; // WHY????
if (save < r4) {
r5--;
}
}
else {
bVar1 = 0;
}
r9 <<= 1;
if (bVar1) {
r9 |= r8;
}
}
}
return r9;
}
s32 sub_8009F68(s32 x, s32 y)
{
s32 uVar1;
s32 sVar1;
uVar1 = y;
if (y < 0) {
uVar1 = -y;
}
sVar1 = 0x100;
for (; uVar1 != 0; uVar1 >>= 1) {
if ((uVar1 & 1) != 0) {
sVar1 = s24_8_mul(sVar1, x);
}
x = s24_8_mul(x, x);
}
if (y >= 0) {
return sVar1;
}
else
return s24_8_div(0x100,sVar1);
}
s32 sub_8009FB8(s32 x, s32 y)
{
s32 r4;
s32 counter;
s32 r5;
s32 r6;
r5 = x;
r6 = y;
if (r5 < 0) {
r5 = -r5;
}
if (r6 < 0) {
r6 = -r6;
}
if (r5 < r6) {
r4 = r5;
r5 = r6;
r6 = r4;
}
if (r6 != 0) {
for(counter = 2; counter >= 0; counter--)
{
r4 = s24_8_div(r6,r5);
r4 = s24_8_mul(r4,r4);
r4 = s24_8_div(r4,r4 + 0x400);
r5 = r5 + s24_8_mul(r5,r4) * 2;
r6 = s24_8_mul(r6,r4);
}
}
return r5;
}
void sub_800A020(s32 *param_1, u32 param_2)
{
#ifndef NONMATCHING
register u32 temp asm("r4");
#else
u32 temp;
#endif
temp = 0xffff0000;
param_1[0] = param_2 >> 0x10;
param_1[1] = param_2 << 0x10;
if ((param_2 & 0x8000) != 0) {
param_1[0] |= temp;
}
}
u32 sub_800A048(u32 *param_1)
{
u32 uVar1;
uVar1 = ((u16)param_1[0] << 0x10) | (param_1[1] >> 0x10);
if ((param_1[1] & 0x8000) != 0) {
uVar1++;
}
return uVar1;
}
UNUSED u32 sub_800A068(u32 *param_1)
{
u32 uVar1;
uVar1 = ((u8)param_1[0] << 0x18) | param_1[1] >> 8;
if ((param_1[1] & 0x8000) != 0) {
uVar1++;
}
return uVar1;
}