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. Unlike my other sfc
branch, the code has been modified only where necessary to continue to function. It works with either agbcc or modern gcc.
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. Recommended for use where patterns likeRandom() & x
orRandom % 2/4/8/16/32...
are used.u32 RandomBits32(n)
: A macro that returns au32
containingn
(0-32) unbiased random bits.bool8 RandomBool()
: A macro that returns a random unbiasedbool8
. Recommended for use in random conditions (e.g.if( RandomBool() )
).u16 RandomRangeFast(u16 n)
: A macro that returns a number from 0 ton
using a fast but biased method. Recommended for use in code that does not affect game mechanics (e.g. code whose results are only visual or audible).u16 RandomRangeGood(u16 n)
: A function that returns a number from 0 ton
using a slower but unbiased method. Recommended for use in code that affects game mechanics.u16 RandomPercentageGood()
: A function that returns an unbiased random number from 0 to 99. Recommended for uses whereRandomRangeGood(100)
would have been used.void StartSeedTimer(void)
: Starts a hardware timer that is used byBootSeedRng()
.
RandomRangeFast
works a lot like the Random() % n
technique currently 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 than RandomRangeGood
because it will only ever do one RNG call. It is almost always substantially faster than Random() % n
because the Game Boy Advance does division using a very slow software routine.
RandomRangeGood
, on the other hand, can make as many RNG calls as it needs to ensure that the generated number is not biased, but usually takes less than 4. Even so, this method will usually be faster than Random() % n
where n is not a constant value because software division is just that slow.
- Remove the separate wild encounter RNG. There really doesn't seem to be any point to it.
- Go through the codebase, find uses of
Random() % x
, and replace them withRandomRangeFast
,RandomRangeGood
,RandomBits
, orRandomBool
as appropriate. Thesfc
branch of this repository has already done this if you need pointers, though I have not thoroughly tested it.
void SeedRng(u16 seed)
: It should not be necessary to reseed the RNG typically, andBootSeedRng()
handles gathering data for you.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.