First steps:

Of course, before you start, you need some debugger. If you were able to buy the no$gba - lucky for you. It seems like it can't be bought any more. That's why i use iDeas. It's slow and the debugger doesn't offer too many options, but at least it get's some jobs done.

Also, you need an image of a Pokemon game. To extract it from your Pokemon cartridge, you'll most likely need a flash module to run the extraction software. If you have a slot2-based flash module, you can start the extraction tool, then switch cartridges and extract the data to slot2. If you only have a slot1-based flash module, you can transfer the data via wireless. This takes a long time (can take an hour for a game), but still you end up with a working copy of your own game.
No matter which way you have to use, "Rudolph" tends to be part of the name of the tool for it.

Memory mapping

Searching with iDeas seems to be impossible, you'd rather like to use some hex editor for it. If you do, you should note some mapping issues. Let's look at the PRNG for an example:
The PRNG starts at 0x0201B9EC when loaded. However, if you look at the file in the hex editor, you will find the instructions at 0x0001F9EC. This means that some things are mapped
File.beginFile.endmem.beginmem.enddiff
0x000040000x0010AF9F 0x020000000x02106F9F +0x01FFC000

Also note, these offsets may and will differ when using different games, versions and language versions. I found 05 49 06 48 0A 68 13 1C 43 43 05 48 18 18 08 60 (which is the PRNG)
in english diamond:0x0001F9EC
in english pearl:0x0001F9EC
in german Diamant:0x0001FA38
so better search for some reference point before starting your experiments.
In my experiments I use an english diamond edition.

Overview of found stuff:

Routine Begin End Input Output
Mersenne Init (prev: unknown1) 0x0201BA1C 0x0201BA4D R0: starting Seed M0 no reg, plenty of mem
MersenneInit.D 0x0201BA50 0x0201BA53 0x021C4D48 = address of PRNG seed
MersenneInit.D 0x0201BA54 0x0201BA57 0x02105BA8 = address
MersenneInit.D 0x0201BA58 0x0201BA5B 0x021C4D50
MersenneInit.D 0x0201BA5C 0x0201BA5F 0x6C078965 = Masuda Factor
Mersenne 0x0201BA60? 0x0201BB43 none?? R0: "random" number
Mersenne.D 0x0201BB44 0x0201BB47 0x02105BA8 - address of Mersenne index number
Mersenne.D 0x0201BB48 0x0201BB4B 0x00001571 - Used as seed for Mersenne-reinit?
Mersenne.D 0x0201BB4C 0x0201BB4F 0x021C4D4C - address of mersenne table
Mersenne.D 0x0201BB50 0x0201BB53 0x02105BAC
Mersenne.D 0x0201BB54 0x0201BB57 0x7FFFFFFF
Mersenne.D 0x0201BB6C 0x0201BB6F 0x9D2C5680 - used in Mersenne
???? 0x02020C2C ???? This is called from PRNG
Pokeradar something 0x0205DED4 0x0205DF43 ??? ???
Pokeradar try 0x0205E30C 0x0205E3EB ??? ???
Pokeradar (shiny patch check) 0x0205E40C 0x0205E475 none R0: 1 for shiny patch, 0 for regular
Pokeradar.D 0x0205E478 0x0205E47B 0x00002008
Pokeradar.D 0x0205E47C 0x0205E47F 0x0000FFFF
PID Generation (wild) 0x02066D90 ??? R4: wanted nature Stack: PID
Check PID vs SIDTID for shinyness 0x02068AAC 0x02068AD3 R0: SIDTID
R1: PID
R0: 1 if PID is shiny, 0 if not
ShinynessCheck.D 0x02068AD4 0x02068AD7 0xffff0000
Division 0x020EBC80 ??? R0: dividend
R1: divisor
R0: quotient R0/R1
R1: remainder R0%R1
Unknown1.D 0x02105BA8 0x02105BAB MersenneInit stores here (index for Mersenne?)
PRNG.D 0x021C4D48 0x021C4D4B Current Seed for PRNG
Mersenne.D 0x021C4D4C 0x021C4D4F Seems to be (initial) Mersenne Table (m0)
Mersenne.D 0x021C4D50 0x021C570F Seems to be (initial) Mersenne Table (624 entrys, each 4 byte)
Starter.D 0x021D9068 0x021D906B 0x00000183 = Starter #1 (when selecting starter)
Starter.D 0x021D906C 0x021D906F 0x00000186 = Starter #2 (when selecting starter)
Starter.D 0x021D9070 0x021D9073 0x00000189 = Starter #3 (when selecting starter)
somewhere in Masuda Loop 0x021ED046: call Masuda cycle
0x021ED068: compare number of trys
??? input??? output???
Determine Encounter Slot 0x0223C5AC 0x0223C647? ??? R0: Index of Encounter Slot
??? ???
0x223CAC6, Determine Encounter Slot
???
First Wondercard (japanese Soulsilver, onscreen)???? 0x02285DE0
Box02 (japanese Soulsilver, onscreen)???? 0x0228BE04

Magic numbers

Sometimes you may encounter some numbers that may look strange at first. In many cases the purpose of a function gets more understandable if you're able to recognize those numbers and their meaning.

hex dec Description
0x27 39 0x270 = 0x27 << 4
0x00000183 387 Pokedex number of Turtwig (starter1)
0x00000186 390 Pokedex number of Chimchar (starter2)
0x00000189 393 Pokedex number of Piplup (starter3)
up to 0x000001ED up to 493 Numbers up to 0x1ED may be pokedex numbers
0x270 624 Size of Mersenne table
0x00002008 8200 = 41*200, used by pokeradar
0x00006073 24691 Used in PRNG, Addition
0x0000FFFF 65535 Bitmask: Lower 16 bit
0x41C64E6D 1103515245 Used in PRNG, Multiplication
0x6C078965 1812433253 Used in Mersenne_init (multiplication)
also used in Masuda Cycle (multiplication)
0x9D2C5680 2636928640 Used in Mersenne (tempering)
0xFFFF0000 4294901760 Bitmask: Upper 16 bit

CMP cheat table for positive values

CMP Rn,Rm -> alu_out = Rn - Rm
EQ Z is set, if Rn=Rm
NE Z is clear if Rn!=Rm
LT V can never be set if both operands are positive.
N is set for Rn<Rm
GT Z is clear if Rn!=Rm
V can never be set if both operands are positive.
N is clear for Rn>=Rm

Offset

Routines in detail

02066D92: PID Generator Called for wild pokemon, not for eggs! Rolls, until nature matches R4, then puts PID on Stackpointer+4 02068884: Returns nature of PID, return value: R0 0206A3D8: Looks very similar to PRNG 020EBC80: Division routine; performs R0 / R1 020EBE88: End of Division
r2 = 0x021C4D50 - 0x04
r2 = 0x021C4D4C
address opcode command alias comment
Mersenne Init
0x0201BA1C B430 PUSH R6,R5 push r5-r6 Pushes some values onto the stack (but not lr)
0x0201BA1E 490C LDR R1 PC+(12*4) r1 = mem[PC+0x30]
r1 = mem[0x0201BA22+0x30]
r1 = mem[0x0201BA20+0x30]
r1 = mem[0x0201BA50]
r1 = 0x021C4D48
Load address of seed into R1
0x0201BA20 2427 MOV R4, 0x27 r4 = 0x27 Load a constant into r4
0x0201BA22 6048 STR R0 [R1+1*4] mem[R1+0x04] = r0
mem[0x021C4D48+0x04] = r0
mem[0x021C4D4C] = r0
Store given value (starting seed M0) in memory
0x0201BA24 490B LDR R1 PC+(11*4) r1 = mem[PC+0x2C]
r1 = mem[0x0201BA28+0x2C]
r1 = mem[0x0201BA54]
r1 = 0x02105BA8
Load next address into R1
0x0201BA26 2001 MOV R0, 0x01 r0 = 0x01 load another constant, into R0
0x0201BA28 6008 STR R0 [R1+0*4] mem [r1+0x00] = r0
mem [0x02105BA8] = 0x01
Write constant One into address
0x0201BA2A 490B LDR R1 PC+(11*4) r1 = mem[PC+0x2C]
r1 = mem[0x0201BA2E+0x2C]
r1 = mem[0x0201BA2C+0x2C]
r1 = mem[0x0201BA58]
r1 = 0x021C4D50
Load address (right behind the one just written)
0x0201BA2C 4B0B LDR R3 PC+(11*4) r3 = mem[PC+0x2C]
r3 = mem[0x0201BA30+0x2C]
r3 = mem[0x0201BA5C]
r3 = 0x6C078965
Load Masuda factor
0x0201BA2E 0124 LSL R4,R4,4 r4 = r4 << 4
r4 = 0x27 <<4
r4 = 0x270
Increase the value from earlier
0x0201BA30 1F0A SUB R2,R1,4 r2 = r1 - 0x04 (Begin of loop) Load address of last stored number
At first iteration, this is address of M0
0x0201BA32 6815 LDR R5, [R2+0x00] r5 = mem[R2+0x00] Restore previous stored number
At first iteration, this is M0, the first given seed
0x0201BA34 0FAA LSR R2,R5,30 r2 = r5 >>0x1e Isolates upper 2 bit from r5
0x0201BA36 406A EOR R2, R5 r2 = r2 xor r5
r2 = (r5>>0x1e) xor r2
lower 2 bit of r2 get influenced by previous upper 2 bit
0x0201BA38 1C15 ADD R5,R2,0x00 r5 = r2 + 0x00
r5 = r2
Copy manipulated value back to R5
0x0201BA3A 435D MUL R5,R3 r5 = r5 * r3
r5 = r5 * 0x6C078965
Multiply manipulated value with mersenne factor
0x0201BA3C 1942 ADD R2,R5,R0 r2 = r5 + r0 Increase number by count
0x0201BA3E 1C40 ADD R0,R0,0x01 r0 = r0 + 0x01 increase r0 (for next cycle)
0x0201BA40 C104 STMIA R1, (r2-r2) mem[r1]=r2; r1=r1+regcount*0x4
mem[r1]=r2; r1=r1+0x4
Store this value and postincrement R1
0x0201BA42 42A0 CMP R4,R0 cmp r4,r0
cmp 0x270,r0
0x270 = 624 = number of entrys for table
0x0201BA44 DBF4 B LT (-0x18) if (r0<0x270) PC = 0x0201BA48-0x18
if (r0<0x270) PC= 0x0201BA30
If not all 624 entrys finished, continue loop
0x0201BA46 4903 LDR R1, PC+(3*4) r1 = mem[0x0201BA4A+0xC]
r1 = mem[0x0201BA48+0xC]
r1 = mem[0x0201BA54]
r1 = 0x02105BA8
Load address (0x1 was stored here)
0x0201BA48 6008 STR R0,R1+0*4 mem[r1+0x00] = r0
mem[0x02105BA8] = r0
mem[0x02105BA8] = 0x270
Store number of calculated table entrys? current index?
0x0201BA4A BC30 POP R6,R5 pop r5-r6 Restore stacked values (not end of function
0x0201BA4C 4707 BX R7 PC = r7 end of function, return
Mersenne RNG
0x0201BA60 B5F8 PUSH LR, R7, R6, R5, R4, R3 push r3-r7, lr Save some values on stack
0x0201BA62 4838 LDR R0, PC+(56*4) r0 = mem[0x0201BA66+0xE0]
r0 = mem[0x0201BB46]
r0 = mem[0x0201BB44]
r0 = 0x02105BA8
Load address of Mersenne index into R0
0x0201BA64 6801 LDR R1, R0+0*4 r1 = mem[r0+0x00]
r1 = mem[0x02105BA8]
Load Mersenne index into R1
0x0201BA66 2027 MOV R0,39 r0 = 0x27 Load a constant (preparation for 0x270)
0x0201BA68 0100 LSL R0, R0, 4 r0 = r0 << 4
r0 = 0x27<<4
r0 = 0x270
Load Mersenne table size
0x0201BA6A 4281 CMP R1,R0 cmp r1,0x270 Compare current index with table size
0x0201BA6C DB54 B LT (84) if (r1<0x270) PC = 0x0201BA70+0xA8
if (r1<0x270) PC = 0x0201BB18
If index is small, jump
0x0201BA6E 1C40 ADD R0,R0,0x1 r0 = r0 + 0x1 r0 = 0x271?
0x0201BA70 4281 CMP R1,R0 cmp r1,0x271? Compare index with next size
0x0201BA72 D102 B NE (2) if (r1 != 0x271) PC = 0x0201BA76+0x4
if (r1 != 0x271) PC = 0x0201BA7A
If index is exact, jump
0x0201BA74 4834 LDR R0, (PC+52*4) r0 = mem[0x0201BA78+0xD0]
r0 = mem[0x0201BB48]
load next address
0x0201BA76
0x0201BA78
F7FF
FFD1
BL, high: 0x7FF
BL, low: 0x7D1
call (PC+high<<12+low<<1)
call (0x0201BA7A-0x1000+0xFA2)
call 0x0201BA1C
Re-Init Mersenne?
0x0201BA7A 4C34 LDR R4, (PC+52*4) r4 = mem[0x0201BA7E+0xD0]
r4 = mem[0x0201BB4E]
r4 = mem[0x0201BB4C]
r4 = 0x021C4D4C
Load address (begin of mersenne table)
0x0201BA7C 4934 LDR R1, (PC+52*4) r1 = mem[0x0201BA80+0xD0]
r1 = mem[0x0201BB50]
r1 = 0x02105BAC
Load another address
0x0201BA7E 4D35 LDR R5, (PC+53*4) r5 = mem[0x0201BA82+0xD4]
r5 = mem[0x0201BB56]
r5 = mem[0x0201BB54]
r5 = 0x7FFFFFFF
Load an interesting constant
Pokeradar something
0x0205DED4 B5F8 PUSH LR, R7, R6, R5, R4, R3 push r3-r7, lr Save some values on stack
TODO
0x0205DF30
0x0205DF32
F000
FA6C
BL, high: 0x
BL, low: 0x
call (PC+high<<12+low<<2)
call (PC+
...
call 0x0205E40C
Call Shiny Check for chaining
TODO
0x0205DF42 BDF8 POP LR, R7, R6, R5, R4, R3 pop r3-r7, lr restore values from stack
Pokeradar try
0x0205E30C B5F8 PUSH LR, R7, R6, R5, R4, R3 push r3-r7, lr Save some values on stack
TODO
0x0205E34A 1C06 ADD R6, R0, 0 r6 = r0 + 0
r6 = r0
Copy r0 (address) to r6
0x0205E34C 7830 LDR R0 R6+0 r0 = mem[r6+0]
r0 = mem[r6]
Get steps since last usage
0x0205E34E 2832 TODO cmp r0, 0x32 At this point, r0 ist number of steps since pokeradar was used last time.
It is compared against 50 - so only after 50 steps, it may be used again.
TODO
0x0205E3EB BDF8 POP LR, R7, R6, R5, R4, R3 pop r3-r7, lr restore values from stack
Shiny Check for Chaining
0x0205E40C B538 PUSH LR,R5,R4,R3 push r3-r5, lr Those values are likely to be overwritten and therefore are saved on the stack
0x0205E40E 2800 CMP R0, 0x00 Z = (r0 == 0x00) Compare R0 (chain size) with zero
0x0205E410 D101 B NE 0x01*2 if (!Z), PC=PC+2
if (r0 != 0), PC=0x0205E416
If chainsize is not zero jump to rest of function
0x0205E412 2000 MOV R0 0x00 r0=0 Prepare zero (false) for return in R0
0x0205E414 BD38 POP PC,R5,R4,R3 pop r3-r5,PC End of funtion, restore values
Note that this last two lines (early termination of function)
are only executed, when R0 = 0 (chain size = 0)
0x0205E416 1C02 ADD R2, R0, 0x00 r2 = r0 + 0x00
r2 = r0
Copy chain size to R2
0x0205E418 21C8 MOV R1, 0xC8 r1 = 0xC8 0xC8 = 200, used in calculation
0x0205E41A 4817 LDR R0 PC+(0x17*4) r0 = mem[PC+0x5C]
r0 = mem[0x0205E41E+0x5C]
r0 = mem[0x0205E41C+0x5C]
r0 = mem[0x0205E478]
r0 = 0x00002008
0x2008 = 8200, used in calculation
0x0205E41C 434A MUL R2, R1 r2 = r2 * r1
r2 = r2 * 200
Multiply chain size with 200
0x0205E41E 1A85 SUB R5 R0 R2 r5 = r0 - r2
r5 = 8200-r2
r5 = 8200-(chainsize*200)
With chainsize near 40, the result is interesting
chainsize 39: r5=400
chainsize 40: r5=200
chainsize 41: r5=0
chainsize 42: r5 negative
0x0205E420 2DC8 CMP R5, 0xC8 cmp r5, 0xC8 Compare chainsize with constant 200.
0x0205E422 DA00 B GT 0x00*2 if (...) PC=PC+0
if (...) PC = 0205E426
if R5 is larger than 200 (chainsize less than 40),
skip correction.
0x0205E424 1C0D ADD R5 R1 0x00 r5 = r1 + 0
r5 = r1
r5 = 200
Correction: If chainsize was 40 or larger, correct r5 as if chainsize was exactly 40.
This makes chains larger 40 useless
0x0205E426 0428 LSL R0, R5, 0x10 r0 = r5 << 16 Puts R5 into R0 (with a little bitshift)
0x0205E428 0C00 LSR R0,R0,0x10 r0 = r0 >> 16 Shifts value down again.
Effectively, the last two instructions move r5 to r0 while killing the upper 16 bit.
For maximum chain size, R0 now is 200=0xC8
0x0205E42A D101 B NE 0x01*2 if (!Z), PC=PC+2
if (r0!=0), PC=0x0205E430
As R0 never is zero at this point, this conditional branch always branches.
0x0205E42C
0x0205E42E
F7C2
FBFE
BL, high: 0x7C2
BL, low: 0x3FE
call (PC+high<<12+low<<2)
call (PC+0xFFC2000+0x7FC)
call (PC-0x3E000+0x7FC)
call (0x0205E430-0x3E000+0x7FC)
call 0x02020C2C
This is a pretty wild uncondional jump that I didn't bother analyzing any further -
as it is only executed if r0 is zero at a point it always will be zero
0x0205E430 0428 LSL R0, R5, 0x10 r0 = r5 << 16 Puts R5 into R0 (with a little bitshift)
0x0205E432 0C00 LSR R0,R0,0x10 r0 = r0 >> 16 Shifts value down again.
Effectively, the last two instructions move r5 to r0 while killing the upper 16 bit.
For maximum chain size, R0 now is 200=0xC8.
Last two lines repeat 0x0205E426. I can only assume that the function at 0x02020C2C
can destroy R0 and that's why it is calculated, again.
Still, as long as 02020C2C is not called from here, this should be unnecessary
0x0205E434 2801 CMP R0 0x01 cmp r0,0x01 Compare R0 (still calculated from chain size) with 0x01
Note, r0 is 200 for maximum chain size and larger for shorter chains.
0x0205E436 D801 B HI 0x01*2 if (...) PC=PC+0x02
if (...) PC=0205E43C
R0 is far from being 1, so this always branches.
But consider R0 being 1 at this point...
0x0205E438 2400 MOV R4 0x00 r4=0x00 Set R4 to zero
(code line never reached)
0x0205E43A E016 B 0x16*2 PC = PC+0x2C
PC = 0x0205E46A
Again, this is not executed
0x0205E43C
0x0205E43E
F7BD
FAD6
BL, high: 0x7BD
BL, low: 0x2D6
call (0x0205E440-0x43000+0x5AC)
call 0x0201B9EC
r0 = prng()
get a random number
0x0205E440 1C04 ADD R4 R0 0x00 r4 = r0 + 0
r4 = r0
copy the random number into R4
0x0205E442 0429 LSL R1 R5 0x10 r1 = r5 << 16 again, moves R5 (200 for max chainsize) with shift.
This time is is put into R1
0x0205E444 480D LDR R0 PC+(0x0D*4) r0 = mem [PC+0x34]
r0 = mem [0x0205E448 + 0x34]
r0 = mem [0x0205E47C]
r0 = 0x0000ffff
65535 is needed for division
0x0205E446 0C09 LSR R1 R1 0x10 r1 = r1 >> 16 Finally, R5 really has arrived, here.
0x0205E448
0x0205E44A
F08D
EC1A
BLX; high: 0x8D
BLX; low: 0x41A
call (0x0205E44C+0x8D000+0x834)
call 0x020EBC80
r0 = r0 / r1; r1 = r0 % r1
r0 = 65535 / (8200 - chainsize*200)
for max chainsize: r0 = 65535 / 200 = 327
0x0205E44C 1C01 ADD R1 R0 0 r1 = r0 + 0
r1 = r0
copy to r1
0x0205E44E 1C49 ADD R1 R1 1 r1 = r1 + 1 for max chainsize: r1 = 328
0x0205E450 0409 LSL R1 R1 0x10 r1 = r1 << 16 Another shift with following backshift
0x0205E452 1C20 ADD R4 R0 0x00 r0 = r4 + 0
r0 = r4
Copy random number back to r0
0x0205E454 0C09 LSR R1 R1 0x10 r1 = r1 >> 16 this is the backshift. For max chainsize r1 = 328
0x0205E456
0x0205E458
F08D
EC14
BLX; high: 0x8D
BLX; low: 0x414
call (0x0205E45A+0x8D000+0x828)
call 0x020EBC82
call 0x020EBC80
r0 = r0 / r1; r1 = r0 % r1
The random number is divided by the previously calculated value.
For max chainsize, this means random/328
This is 0 for random lesser than 328
0x0205E45A 0400 LSL R0 R0 0x10 r0 = r0 << 16 Although division result shouldn't have any high bits,
another shifting is done
0x0205E45C 0C04 LSR R4 R0 0x10 r4 = r0 >> 16 So the division result is put into r4
0x0205E45E 0428 LSL R0 R5 0x10 r0 = r5 << 16 8200 - chainsize*200 (maxchain: 200) starts a journey into R0
0x0205E460 0C00 LSR R0 R0 0x10 r0 = r0 >> 16 8200 - chainsize*200 (maxchain: 200) arrives in R0
0x0205E462 4284 CMP R4 R0 cmp r4 r0 r4 is the division result (range: 0 to 8191, smaller range with longer chainsize)
r0 is the "converted" chainsize (200 - 8000)
0x0205E464 D301 B CC/LO 0x01*2 if (r4<r0) jump 0x0205E46A As r0 has to be zero for shiny, jump is unwanted
0x0205E466
0x0205E468
F7C2
FBE1
BL; high: 0x7C2
BL; low: 0x4E1
call (PC+0x7C2<<12+0x4E1*2)
call (0x0205E46A-0x3E000+7C2)
call 0x02020C2C
(yet) no idea, what this function does.
0x0205E46A 2C00 CMP R4, 0x00 cmp r4, 0x00 R4 has to be zero for the routine to return true
0x0205E46C D101 B NE 0x01*2 if (r4!=0x00) PC=0x0205E472 Skip return of true
0x0205E46E 2001 MOV R0 0x01 r0 = 0x01 Prepare one (true) for return in R0
0x0205E470 BD38 POP PC,R5,R4,R3 pop r3-r5,PC End of funtion, restore values
Note that this last two lines are only executed, when R4 = 0
0x0205E472 2000 MOV R0 0x00 r0 = 0x00 Prepare zero (false) for return in R0
0x0205E474 BD38 POP PC,R5,R4,R3 pop r3-r5,PC End of function, restore values
Note that this last two lines are only executed, when R4 != 0
Check if PID is shiny
0x02068AAC 4B09 LDR R3, PC+(9*4) r3 = mem[PC+0x24]
r3 = mem[0x02068AB0 + 0x24]
r3 = mem[0x02068AD4]
r3 = 0xffff0000
Load a bitmask (upper 16 bit)
0x02068AAE 040A LSL R2 R1 0x10 r2 = r1 << 16 As R1 is PID: load PID.LOW into R2(high)
0x02068AB0 4019 AND R1 R3 r1 = r1 and r3 isolates PID.HIGH in R1(high)
0x02068AB2 4003 AND R3, R0 r3 = r3 and r0 R0 is SIDTID, R3(high) gets SID
0x02068AB4 0400 LSL R0 R0 0x10 r0 = r0 << 16 As R0 is SIDTID, load TID into R0(high)
0x02068AB6 0C1B LSR R3 R3 0x10 r3 = r3 >> 16 SID moves into lower bits of R3
0x02068AB8 0C00 LSR R0 R0 0x10 r0 = r0 >> 16 TID moves into lower bits of R0
0x02068ABA 0C09 LSR R1 R1 0x10 r1 = r1 >> 16 PID.high into lower bits of R1
0x02068ABC 4058 EOR R0 R3 r0 = r0 xor r3 calculates trainer.XID into R1
0x02068ABE 0C12 LSR R2 R2 0x10 r2 = r2 >> 16 PID.low into lower bits of R2
0x02068AC0 4048 EOR R0 R1 r0 = r0 xor r1 merges trainer.XID with PID.high
0x02068AC2 4050 EOR R0 R2 r0 = r0 xor r2 finally, merge PID.low into the rest
0x02068AC4 2808 CMP R0 0x08 cmp r0 0x08 If at this point R0 is <8, the PID is shiny for given SIDTID
0x02068AC6 D201 B CS/HS 0x01*2 if (r0>=0x08) PC=0x02068ACC R0 is too high, jump to negative result
0x02068AC8 2001 MOV R0 0x01 r0 = 1 PID is shiny, prepare true (1) as return value in R0
0x02068ACA E000 B 0x00*2 PC = 0x02068ACE jump to end of function
0x02068ACC 2000 MOV R0 0x00 r0 = 0 PID is nonshiny, prepare false (0) as return value in R0
0x02068ACE 0600 LSL R0 R0 0x18 r0 = r0 <<24 false still is 0, true gets shifted up
0x02068AD0 0E00 LSR R0 R0 0x18 r0 = r0 >>24 and shift down again (unneccessary overflow protection?)
0x02068AD2 4770 BX R14 bx lr End of Function
PRNG-style, german soulsilver
0x02009CB0 6802 LDR R2, R0, 0 R2 = mem[R0+0]
R2 = mem[R0]
R0 seems to be location of current seed
0x02009CB2 4905 LDR R1, +5 R1 = mem{PC+5*4)
R1 = mem[0x02009CB6+14]
R1 = mem[0x02009CCA]
R1 = mem[0x02009CC8]
R1 = 0x41C64E6D
Multiplicative part of PRNG
0x02009CB4 1C13 ADD R3, R2, 0 R3 = R2 + 0x00
R3 = R2
Current Seed?
0x02009CB6 434B MUL R3, R1 R3 = R3 * R1
R3 = R3 * 0x41C64E6D
Multiplication
0x02009CB8 4904 LDR R1, +0 R1 = mem [PC+4*4]
R1 = mem[0x02009CBC+0x10]
R1 = mem[0x02009CCC]
R1 = 0x6073
Additive part of PRNG
0x02009CBA 1859 ADD R1, R1, R3 R1 = R1 + R3
R1 = 0x6073 + R3
Addition
0x02009CBC 6001 STR R0,+0,R1 mem[R0+0]=R1 Store new seed
0x02009CBE 0C08 LSR R0, R1, 0x10 R0 = R1 >> 16 push high to low
0x02009CC0 0400 LSL R0, R0, 0x10 R0 = R0 << 16 push low to high
0x02009CC2 0C00 LSR R0, R0, 0x10 R0 = R0 >> 16 push high to low again
0x02009CC4 4770 BX R14 bx r14 End of function