Past Gen RNG Research

The XD RNG behaves interestingly in quiet areas (areas in which the RNG stays still, such as the top of the Light House in Gateon Port). When generating Pokémon, it only seems to advance to certain frames.

This was starting to annoy me, so I ran a few tests. I set a seed before battling the trainer who has the Shadow Poochyena, caught Poochyena, then checked the PID. "Frame" refers to the number of advances from the seed 0xBEEFCAFE.

Seed: BEEFCAFE (frame 0), PID: 82644778 (frame 421)
Seed: D63CB5C9 (frame 1), PID: 82644778 (frame 421)
Seed: BF14E168 (frame 2), PID: 0257468B (frame 38)
Seed: F2FF9A8B (frame 3), PID: 82644778 (frame 421)
Seed: DBD5BB22 (frame 4), PID: 0257468B (frame 38)
Seed: DD93C901 (frame 25), PID: 8781F01F (frame 104)
Seed: 9855FB18 (frame 50), PID: 82644778 (frame 421)
Seed: 97D18479 (frame 113), PID: A6937915 (frame 252)
As you can see, PID 82644778 seemed to pop up a lot. Also, none of the Pokémon I had with me had the ability Synchronize.
I can confirm the above oddity at the top of the lighthouse. The frame it jumps to depends on the seed you pick though. I was never able to hit a good spread. It sure is weird going back a single frame only to have it jump forwards by 40 frames...

Edit: Regarding the ability thing it is very possible that it uses the top bit of the IVs depending on how the IVs and nature are stored for future encounters of a shadow pokemon. It would be logical that the IVs are stored individually as that is how they are stored for pokemon in your party and opponent's pokemon. Hmm..

Edit 2: If the game stores the IV hex for whatever reason than the ability shouldn't be determined by the IVs at all. Same w/ the PID hex. If it stores it differently then things will be different, and it could have some implications regarding the legality. Especially if the game only stores the gender and nature rather than the PID hex.


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
I've seen this frame forwarding thing in Colosseum as well. I've been trying to score a phys-flawless Adamant Makuhita, and totally failing because no matter what frame I start on, it always forwards the RNG past my desired frame.

For me, it landed on different frames depending on whether the initial frame was odd or even.

#    seed     frame result
-216 56CBEBB6 frame -130[61C676FC]
-206 AEC852A8 frame -130[61C676FC]
-196 B963446A frame -130[61C676FC]
-194 48C80634 frame -130[61C676FC]
-190 A48B5738 frame -130[61C676FC]
-188 559C5F72 frame -130[61C676FC] even end (58)
-186 DDA5397C frame 72  [c252feba] even start (distance 258, length 200)
-155 2444FE0D frame -53 [9ea64105]
-72  75E81646 frame 72  [c252feba]
0    519AEF0E frame 72  [c252feba] (starting seed)
8    972F3496 frame 72  [c252feba]
9    6252D901 frame 91  [175DFEAF]
10   65D557C0 frame 72  [c252feba]
14   15B1E484 frame 72  [c252feba] even end (58)
16   3C2E371E frame 208 [28201714] even start (distance 192, length 148)
31   B6938287 frame 91  [175DFEAF] odd end (60)
33   1241FD39 frame 163 [027736af] odd start (distance 130, length 76)
109  CAABF6F5 frame 163 [027736af] odd end (54)
111  F0B2C517 frame 215 [262B0D0C] odd start (distance 104, length ??
164  36AFCAD2 frame 208 [28201714] even end (44)
166  BD72FFDC frame 312 [8769770b] even start (distance 146, length 56)
171  9FF19EA3 frame 215 [262B0D0C]
222  70EBB6D4 frame 312 [8769770b] even end (90)
There might be a lot fewer viable spreads because of the RNG forwarding itself. Problem is, I'm not seeing a discernible pattern in how far the RNG is forwarded.
Now this seems to be happening in "noisy" areas where the RNG does advance. Except it just appears to skip frames instead of jumping to certain ones, particularly skipping the ones with good IVs. ;_;

Perhaps it's similar to 4th gen, where it chooses a nature then generates a PID until it matches that nature?


Remodeling Kitchens
is a Researcher Alumnusis a Contributor Alumnus
Edit 2: If the game stores the IV hex for whatever reason than the ability shouldn't be determined by the IVs at all. Same w/ the PID hex. If it stores it differently then things will be different, and it could have some implications regarding the legality. Especially if the game only stores the gender and nature rather than the PID hex.
Once someone actually gets through the game, they can see if the PID is the same or the nature is preserved for a given re-encountered shadow pokemon. Maybe the rebattleable sextuplets will preserve?


As for the forwarding "problem", the game is waiting for a specific value to appear before continuing on. It isn't because it's for the nature of the Shadow Pokemon, as the even odd pattern shows. The chance of it advancing to the same PID is much greater than 1/25, as you can see! It's waiting for a certain nature PID to appear for each non-shadow Pokemon before generating each Shadow Pokemon.

It would be good to note the other Pokemon's data that is generated, as the Shadow Pokemon is usually generated last (because it is last in the party almost always).

In Generation III/IV/V, a Trainer's Pokemon have a set nature (and usually IVs). Most of the time, it is a neutral nature with craptastic (0) IVs, unless it is a hard trainer in which it is probably defined as a beneficial one. The game is required to generate a PID for that purpose -- without a PID it can't be a Pokemon due to how the game carries out a battle ('PKMs').

In Colosseum/XD, this is no different. Before the generation of the shadow Pokemon, there is usually at least one non-shadow Pokemon that has to be created. For the one right before the shadow Pokemon, the call structure goes like this:

PID1    undergo a check to see if it matches the pre-set nature, false
PID1    undergo a check to see if it matches the pre-set nature, false
PID1    undergo.... true!

now we have to generate our shadow Pokemon. 
Since the Opponent's IDs are already determined, those 2 calls aren't present.

IVs2    (ability here)
PID1    shadow pokemon PID: PID2_PID1
As you can see, the frame with your shadow Pokemon's PID is 8_9, where the nonshadow is 1_2 (a gap of 7 calls).

With multiple non-shadow Pokemon (3+ Pokemon carried by the opponent), it gets somewhat trickier. This nature lock is compounded further!


Now, to explain OmegaDonut's test. He's in Phenac City, trying to get Makuhita.

Miror B. Peon Trudly has 3 Pokemon -- Duskull, Spinarak, and Makuhita. 3 Pokemon!

Seed	559C5F72

51	D08FBC3F	PID2 (Spinarak)
52	F1352606	PID1 (Spinarak)
		PID (spinarak)	D08FF135 %0x19=0 Hardy
53	BCB2C4B1	xx
54	946054Bxx
55	D79460B3	IV1
56	053208AA	IV2
57	54DBACC5	xx
58	61C6EC74	PID2
59	76FCA967	PID1	
		PID (Shadow Makuhita)	61C676FC
Another One!

Seed	519AEF0E

65	E18F00D9	PID2
66	5A3E4038	PID1
		PID (Spinarak)	E18F5A3E %0x19=0 Hardy
67	3B22BE1B	xx
68	C38E9072	xx
69	452F356D	IV1
70	5B10F27C	IV2
71	46D0B74F	xx
72	C25274D6	PID2
73	FEBA1841	PID1
		PID (Shadow Makuhita)	C252FEBA
So, Spinarak is definitely required to be Hardy. Now what about the Duskull?
WE MUST GO DEEPER! (awwwyeaaahhh)

I need exact data on what the Duskull's PID was, but for now let's assume it was locked Hardy as well. For the first test, only two other Hardy frames appear before the Spinarak Hardy PID:

Frame	Seed		Upper	PID		Nature
28	BE740A6E	BE74	DCE1BE74	meh
29	B6D9B779	B6D9	BE74B6D9	0
30	D6C09C58	D6C0	B6D9D6C0	0
No other time does Hardy occur before this, so if the game was generating a Hardy Duskull, it would then wait until a Hardy Spinarak could occur too. Then it generates the Shadow Makuhita.


Now on to the second test set. This one gives a much clearer result of what's happening, assuming that it's Hardy.

Frame	Seed		Upper	PID		Nature
61	E6BF4685	E6BF	4771E6BF	0
No other time does Hardy occur before this, so if the game was generating a Hardy Duskull, it would then wait until a Hardy Spinarak could occur too. Then it generates the Shadow Makuhita. With this we can combine the two (as they are nice and close together)

0	519AEF0E	Initial
1	xx		OID Load (In Colo it is Pre-Defined?)
2	xx		OID Load (In Colo it is Pre-Defined?)
3	xx		null
4	xx		null
5	xx		IV1 Load
6	xx		IV2 Load
7	xx		null
8	xx		PID1
9	xx		PID2		fails

...	even_odd failing a lot

58	xx		PID2
59	xx		PID1
60	4771D56A	PID2
61	E6BF4685	PID1
		PID (Duskull)	4771E6BF %0x19=0 Hardy
62	xx		IV1 Load
63	xx		IV2 Load
64	xx		blank
65	E18F00D9	PID2
66	5A3E4038	PID1
		PID (Spinarak)	E18F5A3E %0x19=0 Hardy
67	3B22BE1B	xx
68	C38E9072	xx
69	452F356D	IV1
70	5B10F27C	IV2
71	46D0B74F	xx
72	C25274D6	PID2
73	FEBA1841	PID1
		PID (Shadow Makuhita)	C252FEBA
As you can see, the PID frames alternate odd/even (still assuming that Duskull was Hardy).
Regarding Greevil's pokemon the entire PID and all IVs are kept between encounters if you fail to snag the pokemon. The ones that do not get sent out get new stuff generated. This behaviour is likely to be the same for all other future encounters of a shadow pokemon that wasn't caught.

Again, this points to the ability not being determined by the PID or even IVs.

Edit: Non-shadow pokemon do not keep their IVs if they're generated then you lose the battle. Was worth a try...


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
Just when we thought we had the RNG forwarding figured out...

So I found a decent spread for Makuhita that should be valid under the current model. It has a Hardy spread 7 frames before it, and a Quirky nature spread an odd number of frames before it, with no other Hardy spreads in between to interfere.

On frame 145, we have a Brave Makuhita with 29\31\30\20\31\0 IVs (PID: FA6F7EFA).

Starting from seed C00E6D56, we see that Trudly's Duskull gets the first odd-numbered Quirky spread on frame 9, and his Spinarak gets the first even-numbered Hardy spread after that on frame 36, resulting in a shadow Makuhita on frame 43. I was able to hit that just fine.

If I forward the RNG a couple of frames, the game should pick up the next odd-numbered Quirky spread on frame 85, which then should bring up the Hardy spread on frame 138, resulting in our target Makuhita on frame 145. Right? Except when I tried forwarding the RNG two frames at a time, it skipped past the frame 85 Quirky and went straight to the frame 115 Quirky.

But the frame 138 Hardy spread we want his Spinarak to get still comes after frame 115, so no big deal, right? Wrong again. The RNG forwarded past that Hardy spread and picked up the next even-numbered spread on frame 238.

So this speaks to the possibility that there is a minimum frame gap between the Quirky and the Hardy spread. It is at most 25, because the gap between the frame 9 Quirky and frame 36 Hardy is 27 frames.

Still no idea why the frame 85 Quirky was skipped, though.
While SRing for Dragonite in XD I've noticed that the genders for the 5 Ludicolo have been Male, Male, Female, Female, Male every single time over 10+ SRs. So the genders are probably fixed. Also, abilities can be fixed too but I don't know if abilities require RNG calls or not.

Edit: For Poochyena it looks like Bodybuilder Kilen's Zubat must be Serious Female. Ability is a non-factor here as Zubat has only 1 ability. hm... If only I knew how to code I could make some script to find the possible spreads after such a PID.


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
Thanks for pointing out the gender lock, Hozu. It explains that PID-skipping I saw. Hopefully I can get an Colo\XD spread searcher in RNG Reporter soon.

Duskull (Quirky) is locked to male.  Spinarak (Hardy) is locked to female.

Seed C00E6D56
85 [E0DFC14F]  - Expected Quirky (female)
115 [4AF758AA] - Actual Quirky (male)
138 [9BCF3DCA] - Expected Hardy (male)
238 [3268ED54] - Actual Hardy (female)

Seed 13C772AF
51 [A8A4E909] - Expected Quirky (female)
261 [34FBA399]- Actual Quirky (male)

Seed F08995E1
73 [CACD7811] - Expected Quirky (female)
159 [3B84028D]- Actual Quirky (male)

Seed 63D73422
41 [E0DFC14F] - Expected Quirky (female)
71 [4AF758AA] - Actual Quirky (male)

Seed 3CCB97BA
59  [0416D609] - Expected Quirky (female)
117 [32CEC25E] - Expected Quirky #2 (female)
161 [7F0D6783] - Actual Quirky (male)


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
So I previously believed, based on IBM's documentation, that the GameCube clock ticks went into nanoseconds, making it humanly impossible to correctly time seeds on a real GC.

Well, if that were true, I wouldn't have noticed this pattern:

The game (on Dolphin) was reset at more-or-less 40-second intervals 
(didn't use a stopwatch), at which point I recorded the initial seed.

Time(m:s) Seed-Hex  Seed-Dec   Difference
0:20   -  CE79E8A2 3464095906
1:00   -  DBDBCA2F 3688614447 [224518541]
1:40   -  EA5E99BF 3932068287 [243453840]
2:20   -  F8992DCF 4170788303 [238720016]
3:00   -  071BFD5F  119274847 [243453839] 
3:40   -  154C3FC9  357318601 [238043754]
4:20   -  2372308F  594686095 [237367494]
5:00   -  31B71643  834082371 [239396276]
5:40   -  40190F41 1075384129 [241301758]
Average interval: 238281939 ticks / 40 seconds = 5957048 ticks per second (~6 MHz)

That's only 6 million ticks per second, not 1 billion. It still sounds almost humanly impossible, but FRLG RNGers have been successful with worse (16.78 MHz ticks). Colo\XD RNGing should be doable on a real Gamecube by anyone with a LOT of time and patience.

Don't celebrate just yet, though. I'm still working with Zari to see if it's possible to RNG Hordel's Togepi on a real system.


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
It was previously believed that the shiny wondercard generation was a separate method from regular wondercard generation. Turns out, shininess has nothing to do with it.

The alternate method is only used for wondercards that have a fixed gender AND an unfixed nature. The shiny Hydreigon that Kaphotics tested with was the first widely-available card that fit the criteria -- locked to male with no set nature. However, the shiny genderless Golurk uses the normal wondercard method.

Testing with the female-locked Lightningrod Pikachu shows that it also uses the alternate method.
DW Pokemon can be shiny ?

Par ce post, je vous fait part d'une découverte que j'ai faite cet après midi.

Il y a 1 an que les versions BW sont sorties chez nos antipodes. Ces 2 opus nous ont offert des exclusivités que nous n'avions jamais eues auparavant tels que le Pokémon Global Link et son fameux Mondes des rêves ou "Dream World" . Dans ce petit monde, on peut interagir avec des pokés du monde entier et même en ramener quelques uns sur nos versions Noires et Blanches. Cependant, nous, SH, sommes demandé s'il était possible à les avoir sous leurs formes chromatiques. Ainsi plusieurs personnes se sont penchées à ce sujet et une confirmation est tombée quelques mois après la sortie jap des versions Black and White : "Pokemon from the Dream World caught in the High Link cannot be shiny due to a shiny check."

Cependant, il y a quelques jours, une rumeur a été émise sur le site ShiniesHunters disant que ceux-ci pouvaient être shinies. Par conséquent, je me suis mis à tester sur un nidoran obtenu il y a quelques jours auparavant afin de vérifier si c'était vrai ou si ce n'était qu'une simple rumeur mais...

Me croyez-vous ?​

Je crois bien que je me suis trompé quand je disais qu'on ne pouvait pas les avoir en shinies dans le forêt du heylink car tous mes tests prouvent le contraire.

Le PID de ce poké se situe dans les adresses 0225CE90 et 0227A770 de la mémoire RAM. Le PID est sélectionné dès qu'on appuie sur "Oui" lorsque le jeu nous demande si on prend le poké dans l'équipe.

Durant mes tests, j'ai utilisé les saves states de l'émulateur afin de garder le PID, j'ai ensuite, via le PID, créé un SID qui pourrait rendre ce PID shiny (ID xor PID xor PID2 = SID rendant le PID shiny) . J'ai ensuite repris la save stat avant le combat avec ce poké contenant toujours le même PID. J'ai activé le code AR modifiant son SID en remplaçant l'actuel par celui que j'ai obtenu via le calcul précédent et j'ai ensuite engagé le combat et voilà ce que j'ai obtenu.

Pour ce qui est de l'histoire du shiny prevention, je pense que c'est juste appliqués aux pokés distribués via le DW mais je n'en suis pas encore sur à 100% (Je testerai d'ici mercredi ou samedi prochain avec le branette distribué récemment) .

Cependant, j'ai remarqué quelque chose d'assez étrange durant mes tests (sur 3 tests sur 10) . Parfois, quand je changeais mon SID via le code AR et que j'engageais le combat, il arrivait à ce que le PID fût différent par rapport à celui que j'ai enregistré... Cela me laisse un peu perplexe, est-ce le code AR qui fait ça ou est-ce un pseudo "shiny prevention" ? :/

Enfin, cela mérite d'être approfondi ;).


For this post, I express a discovery I did this afternoon.

Do you belive me ?​

The PID of this pokemon is on the adresses 0225CE90 and 0227A770 in the RAM search (DsMuMe). A PID is chosen when we say "Yes" when the game asks to take the DW pokemon.

In my tests, I used the saves states of the emulator (To keep PID) to create a SID that makes this PID in shiny. Then I took the savestate and I used an AR code that makes this SID equal to this equation : PID xor PID² xor ID = SID (Shiny because X xor X = 0). And the Nidoran (From DW) was shiny.

So, the pokemon from DW (Except DW events) CAN BE shiny !
It remains to think.

Sorry if my english is not perfect, I'm french >>.


Dies, died, will die.
is a Researcher Alumnus
this runs on generating any high link poke:

RAM:02018780             shinyPrevent__:                         @ CODE XREF: createPKM__+66j
RAM:02018780 30 1C                       MOVS    R0, R6
RAM:02018782 21 1C                       MOVS    R1, R4
RAM:02018784 FF F7 B6 FB                 BL      checkShiny__
RAM:02018788 01 28                       CMP     R0, #1
RAM:0201878A 02 D1                       BNE     StdPID.Create
RAM:0201878C 01 20 00 07                 MOVS    R0, 0x10000000
RAM:02018790 44 40                       EORS    R4, R0
RAM:02018792             StdPID.Create:                          @ CODE XREF: createPKM__+6Ej
RAM:02018792                                                     @ createPKM__+A6j
RAM:02018792 01 20                       MOVS    R0, #1
RAM:02018794 06 99                       LDR     R1, [SP,#0x18]
RAM:02018796 00 04                       LSLS    R0, R0, #0x10
RAM:02018798 22 1C                       MOVS    R2, R4
RAM:0201879A 02 40                       ANDS    R2, R0
RAM:0201879C 09 04                       LSLS    R1, R1, #0x10
RAM:0201879E 8A 42                       CMP     R2, R1
RAM:020187A0 00 D0                       BEQ     loc_20187A4
RAM:020187A2             loc_20187A2:                            @ CODE XREF: createPKM__+9Aj
RAM:020187A2 44 40                       EORS    R4, R0
RAM:020187A4             loc_20187A4:                            @ CODE XREF: createPKM__+70j
RAM:020187A4                                                     @ createPKM__+98j ...
RAM:020187A4 20 1C                       MOVS    R0, R4
RAM:020187A6 F8 BD                       POP     {R3-R7,PC}
RAM:020187A6             @ End of function createPKM__
so.. no, they can't.

the pid creation itself is pretty interesting, though. it skips the struct that chooses between pid types.


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
The bad news: hitting your seed in XD won't be as easy as changing your GC clock and using emloop to hit the desired time. The seed is determined by the ~6 MHz clock which does not reset to 0 even if you change the time on the GameCube. You can see this if you reset the seconds to 0 on the GameCube clock -- if you do this a couple of times, you'll see that the clock goes from :00 to :01 in varying lengths of time. If you reset the clock early in the 6 MHz cycle, the time period will be closer to a second. If you reset it late, it will go from :00 to :01 almost instantly.

Still, it doesn't mean RNGing XD on a real GameCube will be really difficult, only a bit more complicated. There are two ways we can approach this:

A) Open up a GameCube and disconnect the battery that keeps time when the GameCube is disconnected from power. That way, all that is needed to reset the clock to 0 is flipping the on\off switch on a power strip. Obviously, not everyone will have the technical know-how or tools to do this, but since there are only of handful of obtainable Pokemon in XD, this might not really be a problem.

B) Synchronize the RNGer's computer with the Gamecube clock. The way we would go about this is to have the user start the game and click a button on the PC at the same time. The user would then have to snag a Pokemon and find its IVs\nature in order to determine the associated starting seed (and hence the time). After that, the computer could keep track of the next opportunity for the desired seed to pop up.

B is more complicated from a programming perspective (and therefore complicates my life D:), and would require the user to recalibrate every time they changed the clock on their computer, or after a long period of time has passed. Computer clocks aren't consistent (which is why they need to synchronize with a time server to keep an accurate clock), and after a while there's going to be considerable drift between the computer clock and the GameCube clock.

In any case, we need to know a few things before we can RNG on XD, for which I'd appreciate the help of other researchers:

The exact timing of the clock crystal on the GameCube

I've estimated it to be about 6 MHz here but I'm still going to need exact timing to make this practical for users. I've seen a few top-view pictures of the Gamecube motherboard, but from that angle I can't see any labeling on the crystal. I'd need someone to open up their Gamecube and take a look.

Whether each Pokemon can be found in an area with a quiet or noisy RNG

We've already determined that RNGing for Hordel's Togepi is going to be highly impractical, because all those moving gears and dials in the Outskirt Stand advance the RNG at a pretty fast rate.

How many frames between the start of the game and the moment the Pokemon is generated

Teddiursa, Shellder, Swellow, Beedrill, Lugia, Rhydon are the few Shadow Pokemon that are generated first without interference from the non-Shadow Pokemon. I've already determined that 375451 frames (occasionally 375452) pass between turning on the game and Shellder's generation. I'd like to see if this holds true for the others.
Holy crap. That's a lot of stuff to do.

For the Wii I think the clock battery is at the front end of the Wii, on the right side of the disc tray. You need a little screwdriver to access it. I'm pretty sure that's the clock battery as when I was screwing around with it my time got reset (don't ask what I was doing...). I would think there are other issues with using a Wii instead of a Gamecube though. It's quite possible that the clock is different on the Wii, or even between different models of a Gamecube I would think.

Edit: The PRNG advances at an inconsistent rate in the area where you encounter Teddiursa. Also, for the PKM structure
0x02 - 0x03 is for the held item.


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
So I tried plan B.

The plan was, you would synchronize RNG Reporter with your GameCube with the "Set Tick" button, catch Teddiursa, Shellder, Swellow, Beedrill, or Lugia, determine its IVs and then use them to determine the seed associated with that time. Once Gamecube and RNG Reporter are synchronized, clicking "Get Current Tick" at the same time you start the game should, in theory, list a number that is close to the Gamecube clock value, and hence the seed.

(Remember, 375451 frames pass between the initial seed and generation of Shellder. Occasionally I saw a 375452 frame difference, so I listed it just in case. Where it says)

Target		Target (375452)	Seed		Seed (375452)	PID		Nature	HP	Atk	Def	SpA	SpD	Speed
Start				09578650	3625DED1	bfb9f143	Naughty	1	28	28	2	20	13
331283A6	5FE0D27		A0592889	4898A4BE	4aa581d6	Serious	5	0	17	2	5	15
94B44A14	C182A295	042F6564	4081C475	49a65b31	Naïve	14	16	11	23	10	18
				No close matches here :(
Yeah, that didn't work out here. The most likely explanation is that the Gamecube clock doesn't increase at the rate we think (i.e. not 6 MHz). We're going to need the exact clock crystal rate before we can make any progress.


Dies, died, will die.
is a Researcher Alumnus
misdreavus was asking before, so i might as well put them both in here

4th gen wondercard pids

this is made with an alternate rng that is seeded from timer0 and a counter at 21e19dc. basically, the initial seed looks like ((*timer0) | (*counter << 16)).

after that, the seed is run through the previously-found arng. so you have:

((*timer0 | (*counter << 16)) * 0x6c078965) + 1

and that's the pid. the one that i was watching seemed to skip the shiny prevention check, but that can't be right. i'll have another look later on. (timer0 is running at 33.513982mhz here, so i can't see manipulating it being feasible at all)


Dies, died, will die.
is a Researcher Alumnus
and high link pids:

RAM_ARM9:020186E4             @ =============== S U B R O U T I N E =======================================
RAM_ARM9:020186E4             createPKM__:
RAM_ARM9:020186E4             var_18          = -0x18
RAM_ARM9:020186E4             arg_0           =  0
RAM_ARM9:020186E4             arg_4           =  4
RAM_ARM9:020186E4 F8 B5                       PUSH    {R3-R7,LR}
RAM_ARM9:020186E6 1D 1C                       MOVS    R5, R3
RAM_ARM9:020186E8 06 1C                       MOVS    R6, R0
RAM_ARM9:020186EA 0C 1C                       MOVS    R4, R1
RAM_ARM9:020186EC 00 92                       STR     R2, [SP]
RAM_ARM9:020186EE 02 2D                       CMP     R5, #2          @ is the pokemon being created from the high link?  yes?  skip normal pid generation
RAM_ARM9:020186F0 04 D1                       BNE     loc_20186FC
RAM_ARM9:020186F2 00 20                       MOVS    R0, #0
RAM_ARM9:020186F4 EC F7 FA FF                 BL      rand__
RAM_ARM9:020186F8 04 1C                       MOVS    R4, R0
RAM_ARM9:020186FA 24 E0                       B       PID.TypeChoice
RAM_ARM9:020186FC             @ ---------------------------------------------------------------------------
RAM_ARM9:020186FC             loc_20186FC:                            @ CODE XREF: createPKM__+Cj
RAM_ARM9:020186FC 00 20                       MOVS    R0, #0
RAM_ARM9:020186FE EC F7 F5 FF                 BL      rand__
RAM_ARM9:02018702 07 1C                       MOVS    R7, R0
RAM_ARM9:02018704 FF 21                       MOVS    R1, #0xFF
RAM_ARM9:02018706 8F 43                       BICS    R7, R1          @ pid bic 0xFF- drop the lowest byte of the pid
RAM_ARM9:02018708 2A 06                       LSLS    R2, R5, #0x18
RAM_ARM9:0201870A 00 99                       LDR     R1, [SP]
RAM_ARM9:0201870C 20 1C                       MOVS    R0, R4          @ move the dex number to a1
RAM_ARM9:0201870E 12 0E                       LSRS    R2, R2, #0x18
RAM_ARM9:02018710 FF F7 80 FF                 BL      sub_2018614
if you notice, the game skips the pid type struct if it detects a high link poke. r5 = 2 for basically everything but HL pokes.

basically, it takes u32, bit-clears the lowest byte, ORs that byte with... something(haven't figured it out yet, but it's probably just the lowest byte of the next seed or something- like with shiny wondercards), then XORs the pid with either nothing or 0x10000, based on some random factor i haven't noticed yet.

i am pretty much positive that the lowest byte isn't OR-ed with either the gender value or the number of HL pokes caught up to that point, though. that speculation was wrong.

and no, as discussed earlier, they can't be shiny.
For XD Gale of darkness there is an oddity regarding shadow pokemon that have already been determined. I would have assumed that instead of using 7 calls to make the shadow mon it would use 1 (for the ability) but it actually uses 5 frames. I accounted for it while searching for a spread for Salamence (see pic).
If Manectric were already determined then Ninjask would have to be generated two frames closer to Salamence (12 frames before instead of 14), meaning that there would need to be a valid PID at that spot.

This should have been obvious when taking a look at Greevil's mons after different amount of mons have been determined but I didn't think about it until I needed to search for spreads ahead of time.

Edit: The 2nd gen starters from Mt. Battle are also generated by Method X.


Dies, died, will die.
is a Researcher Alumnus
i had asked on irc about adding something to the OP:

frankly, it's packed with useful breakpoints, variables, routines, data locations, just a lot of stuff that's very useful and relevant to this thread. there's no reason not to add it to the OP.


also possibly these:

though, there's not much related to gen 3 in the OP so i guess it's up to whoever updates it.
RSFRLG Egg Inheritance
[I]Lower Half[/I] of the PID comes from [I]Method 1[/I] when the egg becomes available.
[I]Upper Half[/I] of the PID comes from [I]Method 1[/I] Frame 1. 
IV's come from [I]Method 1[/I] Frame 2.
Inheritance comes from [I]HGSS's Inheritance[/I] [COLOR=red]Frame 6[/COLOR].
I just thought I might correct this:
The inheritance comes from HGSS breeding, 3 frames after the IV frame. So in the above situation, the inheritance would come from frame 5. Personally, I would have phrased it this way:

If the egg is generated on frame 1:
  • the lower half of the egg PID will come from the lower half of the PID (or the upper 16 bits of the seed) on Method 1 frame 1.
If the egg is collected on frame 1:
  • the upper half of the egg PID will come from the lower half of the PID (or the upper 16 bits of the seed) on Method 1 frame 1.
  • the egg IVs come from Method 1 frame 1.
  • the inheritance comes from HGSS breeding frame 4.


is a Programmer Alumnusis a Researcher Alumnus
Ever since I posted this White JP DSi full seed 9 months ago I have been running various attempts to brute force it, while also reading through assembly code looking for any hints, and attempting to hack desmume into enough of a DSi to reach the RNG seeding code (not to mention making an RNG program on the side). None of it seemed to produce tangible results, until now.

It took much too long, but...
We can now do Gen 5 Standard Seed RNG on DSi/3DS.
(I am making the assumption that DSi XL is the same as DSi, since I don't have access to one.)

As many people guessed, it's all in the Nazos, those mysterious bits of junk left on the program stack that make their way into the first 20 bytes of the SHA-1 message.

Other minor differences:

  • Timer0 and VCount have different ranges.
  • On a 3DS (but not on DSi) there is no PM flag set for times after 11:59:59. (In other words, the BCD representation of the PM hours is 0x12, 0x13, 0x14, etc. instead of 0x52, 0x53, 0x54, etc. as it is on the DS and DSi.)

Here are the parameter ranges I've found on two Japanese DSis, one Japanese 3DS, and one EU 3DS with the retail games that I have access to (JP Black & White, EN White). There was no difference in parameters between any of the Japanese DSi/3DS systems (though I haven't done tests for all versions on all systems). The EU 3DS had different parameters, but it was also a different EN White cartridge.

JP Black on JP DSi:
Nazo: 0x02761150
Timer0: 1237, 1238
VCount: 8C
VFrame: 9

JP White on JP DSi and JP 3DS:
Nazo: 0x02761150
Timer0: 1232, 1233, 1234 *
VCount: 8C
VFrame: 9

* Yes, I have seen more than 2 values for Timer0 on my JP White cart
on the same hardware, though I get 1233 most often and I've only gotten
1234 once.

EN White on JP DSi:
Nazo: 0x027601B0
Timer0: 125F, 1260
VCount: 8D
VFrame: 8

EN White on US DSi:
Nazo: 0x027601B0
Timer0: 12BB
VCount: 90
VFrame: 8

EN White (different cartridge) on EU 3DS:
Nazo: 0x027601B0
Timer0: 12BB
VCount: 90
VFrame: 8

EN Black on US DSi:
Nazo: 0x02760190
Timer0: 123C
VCount: 8C
VFrame: 8
I don't have EN Black on hand, but my initial assumption would be that it has the same Nazo, VCount, and VFrame as EN White, but slightly different Timer0 values (i.e. similar to the relationship between JP Black and White).
Thanks to OmegaDonut for working out a full seed for English Black.

Also, perhaps French White is the same as the Japanese games?

I don't see any correlation between these DSi Nazos and their plain DS counterparts, so someone will need to do what I did for the other languages/versions in order to work out the other Nazos. Anybody who has actual retail carts for any of these versions and a DSi/DSiXL/3DS can get in touch with me via PM (or just do it themselves and share it here, of course).

Nazo search process:

  1. Work out a seed by hand as I did here. This has to be done on a real retail cart on an actual DSi/3DS system. This often takes me 1-2 hours, depending on how Timer0 is behaving.
  2. Start a brute force search for the nazo. See below for details on the search I did to find the JP White Nazo.
  3. Wait for a hit. Now that we know what to look for, this should be quick.
Bond697 came across something explaining in more detail what the various other bits of the SHA-1 message actually were and we saw that the touch screen was definitely one of the inputs (among several others). However, I had never been able to affect the seed by using the touch screen, which was a good indication that many of the things used to build the message were not initialized yet at the time of seed creation (hence all the 0 bits).

Also, I'd traced through enough of the code which runs before the message is built to have a high level understanding of what the Nazo values are (basically, some data structures with pointers to allocated memory with specific relationships between them). All of the plain DS Nazos have a specific pattern to them, so it was not unreasonable to think that the DSi Nazos would maintain that pattern.

So, I decided to do a new Nazo search with the following assumptions:

  1. The Nazo will have the same alignment (16 byte aligned) as the DS Nazos.
  2. The pattern for the full 20 bytes of Nazos on a DS (Nazo, Nazo + 0xFC, Nazo + 0xFC, Nazo + 0x148, Nazo + 0x148) will be the same for DSi/3DS Nazos.
  3. The parts of the SHA-1 message that are 0 on the DS will also be 0 on the DSi because the components that they come from aren't initialized yet at the time that the message is constructed.
The brute forcing program I have does a full search of the Timer0(0 - FFFF)/VCount(0-FF)/VFrame(0-F) space (268,435,456 seeds) for a single Nazo value in a bit under 12 seconds on my 2.53GHz Intel Core Duo Mac Book Pro. It's written in OpenCL, so it would be faster on a high end graphics card, but on my 3 year old machine it actually runs slightly faster (and much cooler) on the CPU...

I've run a number of searches totaling a couple months of processing time over the last 9 months, but they were almost all focused on other parts of the message in the wrong assumption that something was fundamentally different on DSi. With the assumptions given above, it took two bruteforcer instances only about 2 weeks to find the JP White Nazo this time. I started first from 0x02200000 and counted up by steps of 0x10 (i.e. 16-byte alignment). About 10 days in (when the search had reached 0x023xxxxx) I started a second search on another machine from 0x02700000 in the hope that the result from this effort was at least an indication of a reasonable area to search. And indeed it was, as that was the search that actually found the JP White Nazo some days later. I verified it against two other seeds I had previously worked out and did a few test RNGs, all with good results.

Since I now knew where to look, the searches for the JP Black and EN White Nazos took less than 15 minutes each, though working out the full seeds to search for took 1-2 hours each. Verifying the Nazo on a 3DS took longer because I wasn't sure on which second the game was actually starting, and the first time I searched on was a PM time, where 3DS seeds are different.

I've noted a few differences when RNGing on a DSi/3DS.

  • For DSi, you need to start 1 second ahead of your target time just like on a DS. For 3DS, you need to start 8 seconds ahead (presumably the extra 7 seconds are to load whatever is needed to play DS/DSi games).
  • I have seen more than 2 Timer0 values for a single cart/DSi pair, as mentioned above.
  • I've found that if I set the time on my DSi two times in a row (i.e. if I feel that I messed up the synchronization with an external clock and decide to redo it immediately), the actual time I end up hitting after the second time setting is 3-4 seconds later than what it should be, which made finding initial seeds a much slower process. I haven't experienced this when doing something similar on a DS, and I haven't tested the behavior on a 3DS.
Bond697, for the specifics on what each part of the SHA-1 message is, and for various discussions
OmegaDonut and everyone else involved in this effort, which ended up cutting the search time down by around a month and a half
Eiganjo, for letting me test (indirectly) on his EU 3DS.

So, have fun until Gen 6 and/or Grey introduce a new, much more random seeding method. :-)


don't glaze me bro
is a Pokemon Researcheris a Programmer Alumnusis a Forum Moderator Alumnusis a Contributor Alumnus
At the moment, we need volunteers with the corresponding language versions to help get DSi\3DS support for those games. Please post if you are able to help (and have lots of patience).


Dies, died, will die.
is a Researcher Alumnus
not nearly as cool as chiizu's stuff, but apparently emerald does have code to seed the main rng. (i say main because i've found at least 3 or 4 others)

ROM:08000560             @ =============== S U B R O U T I N E =======================================
ROM:08000560             @ void __fastcall seedRNG__()
ROM:08000560             seedRNG__:
ROM:08000560 10 B5                       PUSH    {R4,LR}         @ this function never runs
ROM:08000562 06 48                       LDR     R0, =0x4000104  @ Timer1Data
ROM:08000564 04 88                       LDRH    R4, [R0]
ROM:08000566 20 1C                       MOVS    R0, R4          @ Timer1Data to r0
ROM:08000568 6F F0 46 F8                 BL      setRNG__        @ set rng state (0x3005D80) to result of timer1
ROM:0800056C 04 49                       LDR     R1, =0x4000106  @ T1CNT
ROM:0800056E 00 20                       MOVS    R0, #0
ROM:08000570 08 80                       STRH    R0, [R1]        @ turn off timer1
ROM:08000572 04 48                       LDR     R0, =0x2020000
ROM:08000574 04 80                       STRH    R4, [R0]        @ store the result of timer1 to 0x2020000
ROM:08000576 10 BC                       POP     {R4}
ROM:08000578 01 BC                       POP     {R0}
ROM:0800057A 00 47                       BX      R0
ROM:0800057A             @ End of function seedRNG__
ROM:0800057A             @ ---------------------------------------------------------------------------
ROM:0800057C 04 01 00 04 dword_800057C:  .long 0x4000104         @ DATA XREF: seedRNG__+2r
ROM:08000580 06 01 00 04 dword_8000580:  .long 0x4000106         @ DATA XREF: seedRNG__+Cr
ROM:08000584 00 00 02 02 dword_8000584:  .long 0x2020000         @ DATA XREF: seedRNG__+12r
ROM:0806F5F8             @ =============== S U B R O U T I N E =======================================
ROM:0806F5F8             @ void __fastcall setRNG__(unsigned int T1Dat)
ROM:0806F5F8             setRNG__:                               @ CODE XREF: seedRNG__+8p
ROM:0806F5F8 00 04                       LSLS    R0, R0, #0x10   @ dumb typecasting
ROM:0806F5FA 00 0C                       LSRS    R0, R0, #0x10
ROM:0806F5FC 02 49                       LDR     R1, =0x3005D80  @ rng buffer
ROM:0806F5FE 08 60                       STR     R0, [R1]        @ set rng to T1Dat
ROM:0806F600 02 49                       LDR     R1, =0x20249BC  @ rng frame counter
ROM:0806F602 00 20                       MOVS    R0, #0          @ set counter to 0 to signify starting seed
ROM:0806F604 08 70                       STRB    R0, [R1]
ROM:0806F606 70 47                       BX      LR
ROM:0806F606             @ End of function setRNG__

and apparently it was going to work just like fr and lg.