This is a disassembly of Pokémon FireRed and LeafGreen with the original random number generator replaced with the SFC32 random number generator and with additional random number generation functions, which the code has been modified to use. The code compiles under both the agbcc and devkitPRO compilers, but devkitPRO is recommended because it produces smaller and better code. (On my machine, this repo compiles to a binary that is about 300K smaller before padding.)
void BootSeedRng(void)
: Handles RNG state initialization. You must callStartSeedTimer()
first for it to work properly.void BurnRandomNumber(void)
: Advances the RNG state if some other piece of code is not currently using it. Used in VBlank callbacks to prevent potential data corruption.u16 CountLeadingZeroes(u32 x)
: Returns the number of leading zeroes inx
using a de Bruijin algorithm derived from Wikipedia. Ifx
is 0, returns 0. Used byRandomRangeGood
.u16 RandomBits(n)
: A macro that returns au16
containingn
(0-16) unbiased random bits. Used wherever a fixed number of bits was called for.u32 RandomBits32(n)
: A macro that returns au32
containingn
(0-32) unbiased random bits. Not used in this repository.bool8 RandomBool()
: A macro that returns a random unbiasedbool8
. Used for random conditions.u16 RandomRangeFast(u16 n)
: A macro that returns a number from 0 ton
using a fast but biased method. Used in code that does not affect game mechanics (i.e. code whose results are only visual).u16 RandomRangeGood(u16 n)
: A macro that returns a number from 0 ton
using slower but unbiased methods. Used in code that affects game mechanics.u16 RandomPercentageGood()
: A function that returns an unbiased random number from 0 to 99. This is used whereRandomRangeGood(100)
would have been used, as it seems like that is done pretty often.void StartSeedTimer(void)
: Starts a hardware timer that is used byBootSeedRng()
.
Functions and macros starting with an _ are intended for internal use only, the above functions should be used. Here is what they do anyway:
_RandomRangeGood_Multiply
: ImplementsRandomRangeGood
for cases where the argument is a constant._RandomRangeGood_Bitmask
: ImplementsRandomRangeGood
for cases where the argument is not a constant.__is_constexpr
: Used byRandomRangeGood
to determine whether its argument is a constant or not.
RandomRangeFast()
works a lot like the original Random() % n
technique formerly used throughout the game; given a perfect RNG source, it will not actually choose every number in the range with the same probability, but is faster because it will only ever do one RNG call. RandomRangeGood()
can make as many RNG calls as it needs to ensure that the generated number is not biased, but usually takes less than 3.
u16 WildEncounterRandom()
: The separate wild encounter RNG no longer exists.void SeedRng(u16 seed)
: It should not be necessary to reseed the RNG typically, andBootSeedRng()
handles gathering data for you.void SeedWildEncounterRng(u16 seed)
: The separate wild encounter RNG no longer exists.void StartTimer1(void)
: CallStartSeedTimer()
instead, as that's all the original game did with timer 1.
Random32()
is now a function rather than a macro, as SFC32 outputs 32 bits at a time.