nidorans and volbeat/illumise breeding aren't done the same way anymore. in bw1, they were done with normal rng call, but in bw2, they use and inline copy of the rng and a different state that is stored in ram along with the daycare pkms. it looks like "01 pkm1 9f 01 pkm2 9f 01 rng state 9f 01 something 9f" as one long block in ram.
i'm still figuring it out, but here's nidoran breeding as an example:
Code:
MEMORY:021BD3F8 ; =============== S U B R O U T I N E =======================================
MEMORY:021BD3F8
MEMORY:021BD3F8
MEMORY:021BD3F8 nidoranCompute ; CODE XREF: sub_21BD21C+4Ap
MEMORY:021BD3F8 38 B5 PUSH {R3-R5,LR}
MEMORY:021BD3FA 0D 1C MOVS R5, R1
MEMORY:021BD3FC 14 1C MOVS R4, R2
MEMORY:021BD3FE 00 F0 99 F8 BL firstPokemonDitto ; is the first pokemon ditto? if so, return the address of the second one for this calculation
MEMORY:021BD402 05 21 MOVS R1, #5
MEMORY:021BD404 00 22 MOVS R2, #0
MEMORY:021BD406 5F F6 6B FC BL getPKMStat ; fetch species
MEMORY:021BD40A 1D 28 CMP R0, #0x1D ; nido f
MEMORY:021BD40C 02 D0 BEQ loc_21BD414 ; if it is nido f, use special rng
MEMORY:021BD40E 20 38 SUBS R0, #0x20 ; ' ' ; it's not nido f, but is it nido m?
MEMORY:021BD410 02 28 CMP R0, #2 ; nido m is #32, so this restricts this special rng to nido f->nidoking by species values
MEMORY:021BD412 15 D8 BHI locret_21BD440
MEMORY:021BD414
MEMORY:021BD414 loc_21BD414 ; CODE XREF: nidoranCompute+14j
MEMORY:021BD414 A0 68 LDR R0, [R4,#8] ; 6C078965
MEMORY:021BD416 E1 68 LDR R1, [R4,#0xC] ; 5D588B65
MEMORY:021BD418 22 68 LDR R2, [R4] ; lower seed
MEMORY:021BD41A 63 68 LDR R3, [R4,#4] ; upper seed
MEMORY:021BD41C CF F6 7C EF BLX mul64Unsigned__
MEMORY:021BD420 22 69 LDR R2, [R4,#0x10] ; 00269EC3
MEMORY:021BD422 63 69 LDR R3, [R4,#0x14] ; 00000000
MEMORY:021BD424 10 18 ADDS R0, R2, R0 ; rng add
MEMORY:021BD426 4B 41 ADCS R3, R1 ; rng add
MEMORY:021BD428 00 21 MOVS R1, #0 ; store new lower seed
MEMORY:021BD42A 20 60 STR R0, [R4]
MEMORY:021BD42C D8 0F LSRS R0, R3, #0x1F ; r0 = u32 >> 31
MEMORY:021BD42E 49 00 LSLS R1, R1, #1 ; this is 0?
MEMORY:021BD430 63 60 STR R3, [R4,#4] ; store upper seed
MEMORY:021BD432 01 43 ORRS R1, R0 ; r0 | r1, and set state
MEMORY:021BD434 02 D1 BNE loc_21BD43C ; if it's 1, generate a nido m(go to 21BD43C)
MEMORY:021BD436 1D 20 MOVS R0, #0x1D ; if it's 0, continue and generate a nido f
MEMORY:021BD438 28 60 STR R0, [R5]
MEMORY:021BD43A 38 BD POP {R3-R5,PC}
MEMORY:021BD43C ; ---------------------------------------------------------------------------
MEMORY:021BD43C
MEMORY:021BD43C loc_21BD43C ; CODE XREF: nidoranCompute+3Cj
MEMORY:021BD43C 20 20 MOVS R0, #0x20 ; ' '
MEMORY:021BD43E 28 60 STR R0, [R5]
MEMORY:021BD440
MEMORY:021BD440 locret_21BD440 ; CODE XREF: nidoranCompute+1Aj
MEMORY:021BD440 38 BD POP {R3-R5,PC}
MEMORY:021BD440 ; End of function nidoranCompute
the inline rng call used for nidoran and volbeat is based on a seed generated when you first set up your character on starting the game for the first time. this is due to an error on gamefreak's part, however. each time the game starts, this seed should be unique. this function runs on every boot:
Code:
RAM_ARM9:0200C49C ; =============== S U B R O U T I N E =======================================
RAM_ARM9:0200C49C
RAM_ARM9:0200C49C
RAM_ARM9:0200C49C eggSeed ; CODE XREF: sub_200C3B8+4p
RAM_ARM9:0200C49C ; sub_200C574+10p
RAM_ARM9:0200C49C PUSH {R4-R6,LR}
RAM_ARM9:0200C49E MOVS R5, R0
RAM_ARM9:0200C4A0 BL MersenneTwisterHandler__
RAM_ARM9:0200C4A4 MOVS R4, R0
RAM_ARM9:0200C4A6 MOVS R6, #0
RAM_ARM9:0200C4A8 BL MersenneTwisterHandler__
RAM_ARM9:0200C4AC MOVS R2, R4
RAM_ARM9:0200C4AE MOVS R4, #0
RAM_ARM9:0200C4B0 ORRS R4, R0
RAM_ARM9:0200C4B2 MOVS R0, 0x1CC
RAM_ARM9:0200C4B6 STR R4, [R5,R0]
RAM_ARM9:0200C4B8 ORRS R2, R6
RAM_ARM9:0200C4BA ADDS R0, R0, #4
RAM_ARM9:0200C4BC STR R2, [R5,R0]
RAM_ARM9:0200C4BE POP {R4-R6,PC}
RAM_ARM9:0200C4BE ; End of function eggSeed
and it writes the 8-byte seed to 2225E70. however, right after this, the old seed is read into the same spot. the game reads in the save data into the svc stack and then copies the memory into place, overwriting the new seed with the one that was first created. what should happen is that the egg data and rng state should be loaded from the cart then copied into place THEN that function should run and overwrite the old seed with the new one. they happen in the wrong order and thus, you end up stuck with the same seed every time. this also explains the 2 mersenne twister calls that happen on every boot, causing it to always start at 3.