On this page
  1. How it works
  2. History
  3. Related
  4. Games
  5. References
  6. Sources

RNG manipulation steers a game’s random outcomes by changing when or how its generator advances or gets sampled. The code read here establishes three different ways player timing can affect a result, but the atlas has not yet read a source that documents players using them.

  • Call count Dragon Warrior (1986). Reading the controller calls UpdateRandNum, advancing the same generator used by battle code1,2.
  • Frame count Pokémon Emerald (2004). Outside specified battle types, the VBlank handler advances the generator once per frame; after a save load it starts from 03.
  • Hardware timing Pokémon Red and Blue (1996). Each generator call mixes in the hardware divider value, which changes independently of the frame count4.

#How it works

Changing the number of generator calls changes which value a later roll receives. In Dragon Warrior, each controller read advances the 16-bit state before the next battle result is read1,2. In Emerald, waiting changes how many times the fixed-seed sequence advances before a roll3. In Red and Blue, timing a call also changes the divider value mixed into the state4.

These mechanisms establish opportunities to steer outcomes; they do not show a repeatable player method or prove that a specific input produces a chosen result.

#History

Games

GameYearHowNote
Yoshi's Cookie1992Frame countthe setup menu steps the generator every frame, so the time spent there picks the first board
Every claim about this mechanic, by game (2)

References

  1. ^ abGetJoypadStatus steps the generator each time it reads the controller.Codenmikstas/dragon-warrior-disassembly · Ryan8bit, DW Formulas
    How we know
    805GetJoypadStatus:
    ⋮
    807LC60A:  PHA                     ;Prepare to update the random number by first saving registers 
    ⋮
    811LC60E:  JSR UpdateRandNum       ;($C55B)Get random number.
    
    source_files/Bank03.asm lines 805–811 at ebe6a13 · upstream ↗
    If you sit by idly while waiting to make a command, the random generator is run 60 times per second.
    IV, Frequently Asked Questions · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  2. ^ abUpdateRandNum steps a 16-bit state as s←771s+129(mod65536), and battle code reads its high byte, RandNumUB.Codenmikstas/dragon-warrior-disassembly · Ryan8bit, DW Formulas
    How we know
    668UpdateRandNum:
    ⋮
    673LC563:  ASL RandNumLB           ;
    674LC565:  ROL RandNumUB           ;
    ⋮
    687LC57C:  ADC #$81                ;
    
    source_files/Bank03.asm lines 668–692 at ebe6a13 · upstream ↗
    $9495 = $9495 * 771 + 0x81
    III.A, Common algorithms · archived copy ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  3. ^ abEmerald seeds Random from a hardware timer only when the player's naming screen closes, which also sets the trainer ID; the seeding from the real-time clock at power-on is compiled only into pret's BUGFIX build, so after loading a save the generator starts from 0, and the VBlank handler steps it once a frame outside link, Frontier, and recorded battles.Codepret/pokeemerald
    How we know
    108#ifdef BUGFIX
    109    SeedRngWithRtc(); // see comment at SeedRngWithRtc definition below
    
    src/main.c lines 108–110 at 731ad5b · upstream ↗
    208void SeedRngAndSetTrainerId(void)
    ⋮
    210    u16 val = REG_TM1CNT_L;
    211    SeedRng(val);
    ⋮
    228// FRLG commented this out to remove RTC, however Emerald didn't undo this!
    229#ifdef BUGFIX
    
    src/main.c lines 208–236 at 731ad5b · upstream ↗
    365    if (!gMain.inBattle || !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_FRONTIER | BATTLE_TYPE_RECORDED)))
    366        Random();
    
    src/main.c lines 365–366 at 731ad5b · upstream ↗
    700        if (sNamingScreen->templateNum == NAMING_SCREEN_PLAYER)
    701            SeedRngAndSetTrainerId();
    
    src/naming_screen.c lines 700–701 at 731ad5b · upstream ↗
    8COMMON_DATA u32 gRngValue = 0;
    
    src/random.c line 8 at 731ad5b · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

  4. ^ abRandom_ adds the hardware divider register rDIV to the byte hRandomAdd with carry and subtracts it from hRandomSub with borrow; the VBlank handler calls it every frame, and Random returns hRandomAdd.Codepret/pokered
    How we know
    1Random_::
    2; Generate a random 16-bit value.
    3	ldh a, [rDIV]
    4	ld b, a
    5	ldh a, [hRandomAdd]
    6	adc b
    7	ldh [hRandomAdd], a
    8	ldh a, [rDIV]
    9	ld b, a
    10	ldh a, [hRandomSub]
    11	sbc b
    12	ldh [hRandomSub], a
    
    engine/math/random.asm lines 1–13 at af51989 · upstream ↗
    1Random::
    2; Return a random number in a.
    3; For battles, use BattleRandom.
    ⋮
    7	farcall Random_
    8	ldh a, [hRandomAdd]
    
    home/random.asm lines 1–8 at af51989 · upstream ↗
    37	call Random
    
    home/vblank.asm line 37 at af51989 · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-20.

    Checked by a second AI model, 2026-10-21.

    In the claim ledger

Sources

Code

Secondary