mirror of
https://github.com/pret/pmd-red.git
synced 2026-06-16 21:50:21 -05:00
322 lines
5.5 KiB
C
322 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)
|
|
{
|
|
register u32 temp asm("r4");
|
|
|
|
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;
|
|
}
|