1. keep in mind, these random number generators are circular. you can get to any spot in the line from any other spot just by advancing enough. seed = seed * 0x5d588b656c078965 + 0x269EC3 (or any other lcrng) will loop after completing 2^64 advancements.
2. the concept of a "frame" isn't real. it's something used in reporter to count the number of advancements. frames = number of advancements, that's it. kazo's way of doing it is really the best. the only game that had an advancement counter was emerald. i wouldn't expect it to happen again.
3. whoever said you couldn't dick around with the seeds in the mersenne twister seed array was wrong. the seeds sitting in ram in the array aren't finalized. upon retrieval they are tempered like so:
RAM_ARM9:0203F1C4 getNextValue__: @ CODE XREF: mersenneTwisterHandler__+14j
RAM_ARM9:0203F1C4 00 C0 94 E5 LDR R12, [R4] @ load the address of the top of the table into r12
RAM_ARM9:0203F1C8 3C 00 9F E5 LDR R0, =0x9D2C5680 @ tempering mask A
RAM_ARM9:0203F1CC C0 39 9C E5 LDR R3, [R12,#0x9C0] @ load the current word-aligned table pointer value into r3(we already know it's below 0x270, so still insde the current table)
RAM_ARM9:0203F1D0 38 10 9F E5 LDR R1, =0xEFC60000 @ tempering mask B
RAM_ARM9:0203F1D4 01 20 83 E2 ADD R2, R3, #1 @ counter++
RAM_ARM9:0203F1D8 C0 29 8C E5 STR R2, [R12,#0x9C0] @ now that 1 is added to the counter, the current position in our table is updated. store the new value away for safe keeping.
RAM_ARM9:0203F1DC 00 20 94 E5 LDR R2, [R4] @ load the address of the top of the table into r2
RAM_ARM9:0203F1E0 03 21 92 E7 LDR R2, [R2,R3,LSL#2] @ load into r2 the value of the top of the table + the table counter *4(word-aligned, so ((value*4) +top of table) gives you the current table position)
RAM_ARM9:0203F1E4 A2 25 22 E0 EOR R2, R2, R2,LSR#11 @ r2 = r2 ^ (r2 >> 11)
RAM_ARM9:0203F1E8 82 03 00 E0 AND R0, R0, R2,LSL#7 @ r0(currently 0x9D2C5680) = (r2 << 7) & 0x9D2C5680
RAM_ARM9:0203F1EC 00 20 22 E0 EOR R2, R2, R0 @ r2 = ((r2 << 7) & 0x9D2C5680) ^ r2
RAM_ARM9:0203F1F0 82 07 01 E0 AND R0, R1, R2,LSL#15 @ r0 = (r2 <<15) & 0xEFC60000 - eliminates the bottom half of the number
RAM_ARM9:0203F1F4 00 00 22 E0 EOR R0, R2, R0 @ r0 = r2 ^ r0
RAM_ARM9:0203F1F8 20 09 20 E0 EOR R0, R0, R0,LSR#18 @ r0 = r0 ^ (r0 >> 18)
RAM_ARM9:0203F1FC 10 80 BD E8 LDMFD SP!, {R4,PC}
RAM_ARM9:0203F1FC @ End of function mersenneTwisterHandler__
RAM_ARM9:0203F1FC
so all you would need to do to get what you want is figure out what the seeds look like after tempering and change what you need wherever. easy.
4. one entire "pidrng frame advancement" is one run of seed = seed * 0x5d588b656c078965 + 0x269EC3. that's it. it's not half the seed or anything else. take the (big endian) number at 2216244 and feed the next 16 digits into that formula and you have 1 "frame" advancement.
5. no, those numbers with the chatot pitches don't exist in ram. od made those up to make figuring out the pitch easier. it's... ((seed >> 32) * 0x64) >> 32 and having that makes doing chatot pitches more manageable.
and finally:
when the devs need a random number, they use this:
static inline u32 Rand32(RandContext *context, u32 event)
the "context" thing is a way of naming and sorting the many random number generators they use in bw. when the rng is intialized it's given a context "name" sort of thing and each call afterward is referred to using that "name". it's really a pretty clever way to do it using cheap, easy to manage rngs. they're not great for generating random numbers, but they get the job done.
so they would do: (let's say i wanted a random number between 0 and 99)
Rand32(&mainRnd, 100)
and the game would do:
seed(this is the value at 2216244) = seed * 0x5d588b656c078965 + 0x269EC3
return ((seed >> 32) * 100) >> 32
which would give a value between 0 and 99(between 0 and event-1)
and also, there's a lot of info here:
http://projectpokemon.org/wiki/Notable_Breakpoints