Poke_Transporter_GB/source/random.cpp
easyaspi314 750641c78f Prepare for trouble... and make it.... fixed point?
To protect the world from the soft float library...
To unite all arithmetic within our binary...
To denounce the evils of floating point precision...
To save more kilobytes - that's our vision....

(god this is cringe)

All floating point math has been eliminated, and replaced with
equivalent or near-equivalent fixed-point math.

sprite_data.cpp uses Q16, and get_rand_range uses a full Q32 to
ensure that the exact same results are generated as before, at
the cost of some inline assembly to do a umull (__aeabi_lmul is a
little excessive when the lower 32 bits are discarded)

This eliminates all of the expensive double precision float library,
saving a few kilobytes.

Additionally, the unneccessary parts of nanoprintf have been
disabled. There is no need for precision specifiers, long longs, or
floats.
2025-06-30 13:05:32 -04:00

54 lines
1.0 KiB
C++

#include "random.h"
#include <tonc.h>
unsigned int u32_rand;
void rand_set_seed(unsigned int init_seed)
{
u32_rand = init_seed;
}
unsigned int rand_get_seed()
{
return u32_rand;
}
void rand_next_frame()
{
u32_rand = (0x41C64E6D * u32_rand) + 0x6073; // This is the randomization method used in Gen 3
}
u32 get_rand_u32()
{
rand_next_frame();
return u32_rand;
}
u16 get_rand_u16()
{
rand_next_frame();
return (u32_rand >> 16);
}
u32 get_rev_rand_u32(u32 input)
{
return (input - 24691) * 4005161829;
}
u16 get_rev_rand_u16(u32 input)
{
return (get_rev_rand_u32(input) >> 16);
}
// Force ARM mode. In Thumb mode this imports __aeabi_lmul.
__attribute__((target("arm"), noinline))
static unsigned multiply_high(unsigned x, unsigned y)
{
return ((unsigned long long)x * y) >> 32; // umull
}
unsigned get_rand_range(unsigned inc_min, unsigned exc_max)
{
// fixed point: get_rand_u32() / (float)0x100000000 * (exc_max - inc_min) + inc_min
return multiply_high(get_rand_u32(), exc_max - inc_min) + inc_min;
}