mirror of
https://github.com/pret/pokeplatinum.git
synced 2024-11-23 05:49:44 +00:00
252 lines
6.7 KiB
C
252 lines
6.7 KiB
C
#include "math.h"
|
|
|
|
#include <nitro/math/crc.h>
|
|
|
|
#include "heap.h"
|
|
|
|
static u16 LCRNG_NextFrom(u32 *seed);
|
|
|
|
fx32 CalcSineDegrees(u16 degrees)
|
|
{
|
|
if (degrees >= 360) {
|
|
return 0;
|
|
}
|
|
|
|
fx16 sin = FX_SinIdx(CalcAngleRotationIdx(degrees));
|
|
return FX32_CONST(FX_FX16_TO_F32(sin));
|
|
}
|
|
|
|
fx32 CalcCosineDegrees(u16 degrees)
|
|
{
|
|
if (degrees >= 360) {
|
|
return 0;
|
|
}
|
|
|
|
fx16 cos = FX_CosIdx(CalcAngleRotationIdx(degrees));
|
|
return FX32_CONST(FX_FX16_TO_F32(cos));
|
|
}
|
|
|
|
fx32 CalcSineDegrees_Wraparound(u16 degrees)
|
|
{
|
|
degrees %= 360;
|
|
return CalcSineDegrees(degrees);
|
|
}
|
|
|
|
fx32 CalcCosineDegrees_Wraparound(u16 degrees)
|
|
{
|
|
degrees %= 360;
|
|
return CalcCosineDegrees(degrees);
|
|
}
|
|
|
|
u16 CalcAngleRotationIdx(u16 degrees)
|
|
{
|
|
if (degrees >= 360) {
|
|
return 0;
|
|
}
|
|
|
|
return FX_DEG_TO_IDX(degrees * FX32_ONE);
|
|
}
|
|
|
|
u16 CalcAngleRotationIdx_Wraparound(u16 degrees)
|
|
{
|
|
degrees %= 360;
|
|
return CalcAngleRotationIdx(degrees);
|
|
}
|
|
|
|
fx32 CalcSineDegrees_FX32(fx32 degrees)
|
|
{
|
|
u16 degreesUnshifted = degrees >> FX32_SHIFT;
|
|
return CalcSineDegrees_Wraparound(degreesUnshifted);
|
|
}
|
|
|
|
fx32 CalcCosineDegrees_FX32(fx32 degrees)
|
|
{
|
|
u16 degreesUnshifted = degrees >> FX32_SHIFT;
|
|
return CalcCosineDegrees_Wraparound(degreesUnshifted);
|
|
}
|
|
|
|
#define LCRNG_MULTIPLIER 1103515245L
|
|
#define LCRNG_INCREMENT 24691
|
|
|
|
static u32 sLCRNGState;
|
|
|
|
u32 LCRNG_GetSeed()
|
|
{
|
|
return sLCRNGState;
|
|
}
|
|
|
|
void LCRNG_SetSeed(u32 seed)
|
|
{
|
|
sLCRNGState = seed;
|
|
}
|
|
|
|
u16 LCRNG_Next()
|
|
{
|
|
sLCRNGState = sLCRNGState * LCRNG_MULTIPLIER + LCRNG_INCREMENT;
|
|
return sLCRNGState >> 16;
|
|
}
|
|
|
|
// Matsumoto, M. & Nishimura, T. 1998. "Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator."
|
|
#define MT19937_N 624 // degree of recurrence (number of total words)
|
|
#define MT19937_M 397 // middle word offset
|
|
#define MT19937_W 32 // word size (number of bits)
|
|
#define MT19937_R 31 // separation point of a single word; number of bits of the lower bitmask
|
|
#define MT19937_F 1812433253 // additional initialization constant
|
|
#define MT19937_A 0x9908B0DF // coefficient of the rational normal form twist matrix
|
|
#define MT19937_B 0x9D2C5680 // tempering bitmask
|
|
#define MT19937_C 0xEFC60000 // tempering bitmask
|
|
#define MT19937_S 7 // tempering bitshift (masked against B)
|
|
#define MT19937_T 15 // tempering bitshift (masked against C)
|
|
#define MT19937_U 11 // tempering bitshift (not masked)
|
|
#define MT19937_L 18 // tempering bitshift (not masked)
|
|
|
|
#define MT19937_UMASK (0xFFFFFFFF << MT19937_R)
|
|
#define MT19937_LMASK (0xFFFFFFFF >> (MT19937_W - MT19937_R))
|
|
#define MT19937_DEFAULT_SEED 5489
|
|
|
|
u32 ARNG_Next(u32 seed)
|
|
{
|
|
return seed * MT19937_F + 1;
|
|
}
|
|
|
|
static u32 sMTRNGState[MT19937_N];
|
|
static int sMTRNGIndex = MT19937_N + 1;
|
|
static u32 sMTRNGXor[2] = { 0, MT19937_A };
|
|
|
|
void MTRNG_SetSeed(u32 seed)
|
|
{
|
|
sMTRNGState[0] = seed;
|
|
for (sMTRNGIndex = 1; sMTRNGIndex < MT19937_N; sMTRNGIndex++) {
|
|
sMTRNGState[sMTRNGIndex] = MT19937_F * (sMTRNGState[sMTRNGIndex - 1] ^ (sMTRNGState[sMTRNGIndex - 1] >> (MT19937_W - 2))) + sMTRNGIndex;
|
|
}
|
|
}
|
|
|
|
u32 MTRNG_Next()
|
|
{
|
|
u32 result;
|
|
if (sMTRNGIndex >= MT19937_N) {
|
|
if (sMTRNGIndex == MT19937_N + 1) {
|
|
MTRNG_SetSeed(MT19937_DEFAULT_SEED);
|
|
}
|
|
|
|
int i;
|
|
for (i = 0; i < MT19937_N - MT19937_M; i++) {
|
|
result = (sMTRNGState[i] & MT19937_UMASK) | (sMTRNGState[i + 1] & MT19937_LMASK);
|
|
sMTRNGState[i] = sMTRNGState[i + MT19937_M] ^ (result >> 1) ^ sMTRNGXor[result & 1];
|
|
}
|
|
for (; i < MT19937_N - 1; i++) {
|
|
result = (sMTRNGState[i] & MT19937_UMASK) | (sMTRNGState[i + 1] & MT19937_LMASK);
|
|
sMTRNGState[i] = sMTRNGState[i + (MT19937_M - MT19937_N)] ^ (result >> 1) ^ sMTRNGXor[result & 1];
|
|
}
|
|
|
|
result = (sMTRNGState[MT19937_N - 1] & MT19937_UMASK) | (sMTRNGState[0] & MT19937_LMASK);
|
|
sMTRNGState[MT19937_N - 1] = sMTRNGState[MT19937_M - 1] ^ (result >> 1) ^ sMTRNGXor[result & 1];
|
|
sMTRNGIndex = 0;
|
|
}
|
|
|
|
result = sMTRNGState[sMTRNGIndex++];
|
|
result ^= (result >> MT19937_U);
|
|
result ^= (result << MT19937_S) & MT19937_B;
|
|
result ^= (result << MT19937_T) & MT19937_C;
|
|
result ^= (result >> MT19937_L);
|
|
|
|
return result;
|
|
}
|
|
|
|
void CreateAffineTransformationMatrix(MtxFx22 *matrix, u16 degrees, fx32 xScale, fx32 yScale, u8 mode)
|
|
{
|
|
if (mode == AFFINE_MODE_MAX_256) {
|
|
degrees = (u32)(0xFFFF * degrees) >> 8;
|
|
} else if (mode == AFFINE_MODE_MAX_360) {
|
|
degrees = (u32)(0xFFFF * degrees) / 360;
|
|
}
|
|
|
|
MTX_Rot22(matrix, FX_SinIdx(degrees), FX_CosIdx(degrees));
|
|
MTX_ScaleApply22(matrix, matrix, xScale, yScale);
|
|
}
|
|
|
|
static inline void CalcCrossProduct(const VecFx32 *a, const VecFx32 *b, VecFx32 *outResult)
|
|
{
|
|
outResult->x = 0;
|
|
outResult->y = 0;
|
|
outResult->z = FX_Mul(a->x, b->y) - FX_Mul(b->x, a->y);
|
|
}
|
|
|
|
s32 CalcDotProduct2D(s32 x0, s32 y0, s32 x1, s32 y1, u32 unused)
|
|
{
|
|
VecFx32 vec0, vec1, vecResult, cross;
|
|
fx32 crossMagnitude;
|
|
fx32 dotProduct;
|
|
s32 result;
|
|
|
|
VEC_Set(&vec0, x0 << FX32_SHIFT, y0 << FX32_SHIFT, 0);
|
|
VEC_Set(&vec1, x1 << FX32_SHIFT, y1 << FX32_SHIFT, 0);
|
|
CalcCrossProduct(&vec0, &vec1, &cross);
|
|
crossMagnitude = cross.x + cross.y + cross.z;
|
|
|
|
VEC_Set(&vec0, y0 << FX32_SHIFT, x0 << FX32_SHIFT, 0);
|
|
VEC_Normalize(&vec0, &vecResult);
|
|
VEC_Set(&vec0, x0 << FX32_SHIFT, y0 << FX32_SHIFT, 0);
|
|
VEC_Set(&vec1, x1 << FX32_SHIFT, y1 << FX32_SHIFT, 0);
|
|
VEC_Subtract(&vec1, &vec0, &cross);
|
|
|
|
dotProduct = VEC_DotProduct(&vecResult, &cross);
|
|
result = dotProduct >> FX32_SHIFT;
|
|
result = MATH_IAbs(result);
|
|
|
|
if (crossMagnitude <= 0) {
|
|
result *= -1;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
s32 CalcRadialAngle(u16 radius, s32 distance)
|
|
{
|
|
s32 circumference = FX_Mul((2 * radius) << FX32_SHIFT, FX32_CONST(3.140f)) >> FX32_SHIFT;
|
|
return (distance * 0xFFFF) / circumference;
|
|
}
|
|
|
|
u32 SumBytes(const void *data, u32 size)
|
|
{
|
|
u32 sum = 0;
|
|
for (int i = 0; i < size; i++) {
|
|
sum += ((const u8 *)data)[i];
|
|
}
|
|
|
|
return sum;
|
|
}
|
|
|
|
void EncodeData(void *data, u32 size, u32 seed)
|
|
{
|
|
u16 *halfWords = (u16 *)data;
|
|
for (int i = 0; i < size / 2; i++) {
|
|
halfWords[i] ^= LCRNG_NextFrom(&seed);
|
|
}
|
|
}
|
|
|
|
void DecodeData(void *data, u32 size, u32 seed)
|
|
{
|
|
EncodeData(data, size, seed);
|
|
}
|
|
|
|
static u16 LCRNG_NextFrom(u32 *seed)
|
|
{
|
|
*seed = *seed * LCRNG_MULTIPLIER + LCRNG_INCREMENT;
|
|
return *seed >> 16;
|
|
}
|
|
|
|
static MATHCRC16Table *sCRC16Table = NULL;
|
|
|
|
u16 CalcCRC16Checksum(const void *data, u32 dataLen)
|
|
{
|
|
return MATH_CalcCRC16CCITT(sCRC16Table, data, dataLen);
|
|
}
|
|
|
|
void InitCRC16Table(enum HeapId heapID)
|
|
{
|
|
GF_ASSERT(sCRC16Table == NULL);
|
|
sCRC16Table = Heap_AllocFromHeap(heapID, sizeof(MATHCRC16Table));
|
|
MATH_CRC16CCITTInitTable(sCRC16Table);
|
|
}
|