Pokémon Box Ruby and Sapphire doesn't use the same seeding function as the R/S carts when playing your GBA save on the GC/Wii. Likely being seeded by the GC. How unfortunate.

Edit: Doesn't appear to be a 16bit seed either... huh.

Turns out that due to primarily not getting Method 1 spreads I was getting the wrong results. Box seeds the same way as normal, using the GBA RTC. However with alternate spreads, like Method 4 this opens up other possibilities.

Edit: Only some mons seem to be generated by Method 4 always... the rest are normal. Regirock seems to be Method 4, while starters are Method 1. One would have to test which ones always seem to be one method or the other.

Edit 2: For live battery carts even when they're disconnected the R/S Box game seems to keep tracks of it, even across SRing. Meaning that the seeding is exactly the same as your GBA cart.

Pokemon Channel Jirachi is generated using the same RNG as XD/Colosseum. It's seeded in the same way (based off the RTC of the Wii/GC).

All this is done in sub_8008ec50 and the rng is sub_8010e2d8 using r3 as a parameter to the RNG as the exclusive upper bound for the RNG call. Just like the other games:
seed = seed * 0x343fd + 0x279ec3
result (in r3) = seed * max (the current value of r3) >> 16.
Note: the game's code doesn't exactly do that, also an extra call to clear the top 16 bits is used after most every rng call.

The generation is as follows:
sid
upid
lpid
then a shiny check is done. If the pid 0x80000000 is not shiny then upid = upid ^ 0x8000, else leave the pid alone.
The SID is combined with the static ID (0x9cba for reference) and setup to be sent to the gba.
Then a rand(8) is called and if it's >= 4 salac berry, else ganlon.
A rand(0x10) is called and if it's >= 8 the OT is from ruby, else it's from sapphire.
A rand(0x20) is called and if >= 16 the OT is female if < 16 it's male.
They probably did this to make it more "random", but it could be simplified to if the high bit is 1 do something else do something else.

code for the gender call(Move your mouse to reveal the content)code for the gender call (open)code for the gender call (close)

Hide(Move your mouse to the hide area to reveal the content)Show HideHide Hide

About the game's RNG:
It's really is identical to XD/Colo rng.
Seeding:
at loc_800363B8 it calls sub_800CE6E4 which runs the command mftb r3 and then the loc stores that value to the seed in memory. That means we'd need to be accurate to the nearest nanosecond to hit seeds.

RNGs:
There's 3 different rng subroutines which are called. They are all next to each other at 8010E250, 8010E280, and 8010E2D8.

channel seeds its rng via the time-base register @ 800CE6E4. "mftb" is an instruction that transfers the value of the time-base register in the console to the given register in the instruction(here being "mftb r3"). more info here:

img of researcher(Move your mouse to reveal the content)img of researcher (open)img of researcher (close)

Pickup only works if you don't run.

Carrying 6 Pickup Mons and defeating a wild poke:
It cycles 7 times after battle if you don't get a pickup, 8 times if one gets a pickup, hence a calc proccing another calc immediately after.

Exiting Seed from the battle is considered the Initial Seed for this post:

Initial

Code:

Advanced Once,
if SEED*100>>32 is < 10
then [SEED+1]*100>>32 for Pickup Item Value (0-99)
else, advance once and repeat for next slot.
end
6 iterations, there is one calc afterwards for something else.

Pickup Table located here, although the placement for the 1%'s is off. Prism Scale is 98 for level 100 (leftovers is 99).

The Phanpy in slot 2 picked up a different item to the others even though they should be in the same Item Category. That's the only solution I can think of.
I haven't tested it with other monz because I've spent too much time finding good Pickup Seeds (5 Rare Candies OMG!).

EDIT: I've tried it again with different levels. My level 84 Phanpy picked up a PPup with 94 rather than a Max Revive.

so this morning chiizu was asking me about a function in the breeding module that has to do with checking for a ditto then advancing the rng once if one exists. i hadn't had time yet, so i put a copy on pastebin for him(and a copy of the dwAbil function) and fired up ida and we went to work.

turns out that the game checks the ability of the ditto(or mother) and if it's ability 0, the baby has an 80% chance of abil 0, if abil 1 an 80% chance of abil 1, and if it's the dw abil, the percentages become 20/20/60 leaning towards the dw abil.

here's where it gets sort of interesting. if you have a ditto, the previous function still runs. however, right after it another function runs that checks if you have a ditto. if you do have one, it advances the rng and does u32 >> 31 and stores the result of that calculation as the ability. this limits ditto-based breeding to abil 0/1.

loc_21DC442 is where the moody stat advances are handled. It calls a rand 0x2a (42) which it uses as a pointer into a table of halfwords located at 0x02271dc8. This table consists of pairs of stats, one that's lower and one that's dropped and it does not contain pairs such as 1,1 so that you can't raise and lower the same stat. 1 = Atk, 2 = Def, 3 = SpA, 4 = SpD, 5 = Spe, 6 = accuracy, 7 = evasion. It stores these numbers in R5, the lowered stat, and R6, the raised stat. Also Battle Subway cheating is a total lie as we all expected.

the egg will always get the nature of the pkm with the everstone. if both have an everstone, the egg with get the nature that follows u32 >> 31, 0 being nature 1(daycare pkm1) and 1 being nature2(daycare pkm2). no one bothered to look, thinking the rand call in the function was for the 50/50 on the everstone.

get a random number 0-0xFFFF and check if it's equal to 0x4000, 0x8000, or 0xC000. if it's equal to any of the 3, pick a pkm party slot via rand() % 6. check to be sure that slot is filled, repeating the process to pick a new one if it's not. once they're sure it is, call rand again and do rand() & 0xFF. take the byte and do & 7 and store the result, repeating the process if it results in 0. once they have a non-zero result, take the byte and do & 0xF0. store this result if it's non-zero. at this point, they take the byte, & 0xF3 and add 1. this result is stored to the pkm file as field 0x22.

and no, there's no check for an egg or anything else. anything can be infected with or spread pokerus. also, it can spread to either pokemon surrounding the infected one, not just the next one in line like i see people saying occasionally.

correction: eggs cannot be infected with pokerus in any gen 3 game. they can, however, have it spread to them from another party member.

it's probably not something we ever even thought about since most people breed with dittos unless they're going for a dw ability, which is just a straight 20/20/60 if the mother has it and dittos have their own special ability fixing function.

if rand(100) < 20, set abil 0. if < 40, set abil 1. if >= 40, set ability 2(dw abil).

**however, it turns out the game never actually uses the result of all that work it does. the ability still seems to be pid >> 16 & 1, even though all of that other code runs and selects a pid based on the mother's ability. it's unused code that actually does run, which doesn't make much sense at all.

basically, it does getPKMStat(egg, ABILITY, 0) which gets the ability using pid >> 16 & 1, it doesn't refer to the stored ability at all.
-----------------------------------------------------

any nido except nidorina and nidoqueen will cause the nidoran compute function to run. it checks for a species from 0x1D to 0x22 excluding 1E and 1F.

-----------------------------------------------------

if you're using a ditto to breed, the previous calc will still happen. however, right afterward there is another check to see if a ditto is involved. if so, the game does rand(2) to pick which ability to use. the 0 and 1 results directly correspond to the possible abilities.

i found something by accident last night. it's only relevant to gen 4 wondercards so it has no real application, but is interesting trivia nonetheless. so, gen 4 wondercard pids are made from a combo of a counter and a timer0 value. no one really knew what that value was though. turns out it's part of "OSi_TickCount", a volatile 64-bit number that holds the current value of the tick system for the ds.

most ds games have a function that runs as the very first thing once system control is passed to main() and this function is usually called "SystemInit" and it turns on systems that the game will use, allocates system memory, stuff like that. in SystemInit, gamefreak turns on the tick system(OS_InitTick), turns on the graphics system, the fixed point math system, the alarm system, starts pxi, initializes the os, etc. OS_InitTick sets OSi_TickCount to 0, turns on timer0, sets OSi_UseTick to true(bool variable that indicates the system is on), sets OSi_NeedResetTimer to false(bool var that says whether or not the tick counter should be reset to 0), and sets the timer0 interrupt callback to OSi_CountUpTick() to insure that OSi_TickCount increments.

So there's a callback to increment this variable, but when does the callback run? It runs when timer0 overflows. when timer0 hits 0xFFFF and resets to 0x0000, an interrupt fires and OSi_CountUpTick runs. it does OSi_TickCount++ and some housekeeping and that's it.

what does this have to do with pokemon? when a 4th gen wondercard is created, OS_GetTick is called. it makes a number using OSi_TickCount and the current value of timer0 that looks like this:

so the exact pids for gen 4 wondercards are the lowest 16 bits of the tick counter << 16 and then OR-ed with timer0. gamefreak is getting back a 64-bit number and taking the lower half as the pid, basically. if they used the upper half, wondercard pids would be rng-able.

in white, the tick system enabled bool is at 2151350, 2151354 is the bool for resetting the counter, and 2151358-215135F(215135C then 2151358) is the actual tick counter.

in hgss the starting value is 21E19D4.

and just as an idea of how fast this stuff is: timer0 moves(does one full interval of 0-FFFF) at F/64 seconds, where F is the CPU speed of the ARM7 CPU. 0x100 ticks(which is 0x100/256d overflows of timer0) takes all of roughly 7.5 video frames, a little over 1/10th of a second or about .15 seconds total.

so the first pid is ((counter << 16) | timer0) * 6C078965 + 1.

also, since i'm talking about gen 4 wondercards, the pid value on the card has 3 states. if it's greater than 1, then the pid = that number. if the pid value on the card is 1, the pid is generated dynamically. if the value on the card is 0 the pid is also generated dynamically, but the shiny check never happens. so if there's a card out there with a 0 for the pid value, it can be shiny. i've not ever seen one, but who knows.

Credits to chiizu for making the searcher, helping me make it compile on my end, and actually finding the black2 parameters.
Future searches should be much faster since now I have GPU acceleration working correctly.

Not sure if it's still needed, but by the time I saw chiizu's new post I already did it, so might as well post regardless.

Click to expand...

We still need this data for the various games. What I and Slashmolder posted above are the details for DS / DS Lite. The data you are providing will be used to work out the necessary details to support the games on DSi / 3DS.