Luck manipulation (Generation I)

From Glitch City Wiki
Revision as of 10:58, 2 March 2019 by >Bbbbbbbbba (Added description of RNG and DSum manipulation.)
This article is incomplete. Please feel free to add any missing information about the subject. It is missing: {{{1}}}.

Pseudorandom number generation in Pokémon Red, Blue, and Yellow uses the rDIV function, which is stored in hardware and thus makes intentionally landing on a specific value in these games very difficult and unreliable. The only known emulators that emulate this function properly are BGB, Sameboy, and Gambatte-Speedrun. The function also behaves differently between the original Game Boy, Game Boy Color, Super Game Boy, Super Game Boy 2, and 3DS Virtual Console. However, certain series of timed inputs based on the DMG-001's rDIV function have been discovered for use in speedrun routes and work as intended nearly all of the time provided the player does not miss any input windows. The save file's in-game time also affects the initial seed, and at times can cause one of these procedures to fail. What is needed to fix this is simply saving again.

Encounter slots are determined by a variable known as the DSum (the sum of hRandomAdd + hRandomSub in random.asm in pret's disassembly), which can be predicted within a reasonable range once the current value is guessed through the encounter slot of the last wild Pokémon encountered.

Mechanics of the RNG

The RNG itself is a simple function:

Random_::
; Generate a random 16-bit value.
	ld a, [rDIV]
	ld b, a
	ld a, [hRandomAdd]
	adc b              ; add [rDIV] and the carry flag (either 0 or 1) to hRandomAdd
	ld [hRandomAdd], a
	ld a, [rDIV]
	ld b, a
	ld a, [hRandomSub]
	sbc b              ; subtract [rDIV] and the carry flag (which will come from the above addition) from hRandomSub
	ld [hRandomSub], a
	ret

Here, rDIV is the Divider Register, which is initialized to a fixed value during the booting process, and is incremented at a rate of 16384Hz (~16779Hz on SGB).

At the very beginning of the game's startup process (before the copyright screen), hRandomAdd ($FFD3) and hRandomSub ($FFD4) are zeroed with the entire HRAM; apart from that, Random_ is the only place in the code that directly changes them. If the exact timings and circumstances (actually only the carry flag matters) of those calls can be predicted (e.g. in a TAS or shortly after a hard reset), then the results can be predicted too. That's the principle behind luck manipulation.

Advancement of RNG

Usually, the RNG is advanced (i.e. Random_ is called) whenever a random number is needed. In addition, it is also advanced once per frame during the V-Blank interrupt. Since the game doesn't need random numbers very often, the majority of RNG advancements come from the V-Blank.

Since the timing of the V-Blank interrupt itself is fixed, the timing of those framely RNG advancements only depend on the few lines of code between the start of the VBlank function and the Random_ call. As a result, the processor time taken by many things that happen during the main loop doesn't actually change the timing of framely RNG advancements. This fact makes luck manipulation much simpler.

DSum manipulation

The "DSum manipulation" is considered one of the easier RNG manipulation techniques because it doesn't require frame-level precision. The DSum is just the sum of hRandomAdd and hRandomSub (mod 256). Since during any RNG advancement, the main part of their change is rDIV being added to the former and subtracted from the latter, the DSum remains nearly constant after a single RNG advancement.

Two factors cause the DSum to change:

  • A carry flag is added to hRandomAdd and subtracted from hRandomSub, but they are not the same carry flag. The carry flag added to hRandomAdd comes from some previously executed code, and the carry flag subtracted from hRandomSub comes from the addition to hRandomAdd.
  • Since the value of rDIV is read twice, it may change between those two reads.

Their effects can be evaluated as follows:

  • During the framely advancement (the most frequent type of advancement), the carry flag added into hRandomAdd comes from PrepareOAMData, which prepares an OAM buffer from the overworld sprites. It is activated in the overworld and deactivated during a battle. As a side effect, it always sets the carry flag to 0 when it's activated, and to 1 when it's deactivated. This means that during a battle, this factor increases DSum by 1 every frame.
  • The carry flag subtracted from hRandomSub comes from the previous addition. Since rDIV changes regularly in a range of [0, 255], the number added can be considered to be about 128 on average, so a carry happens about every two frames on average. This means that this factor always decreases DSum by about 0.5 every frame on average.
  • A change of rDIV between the two reads is comparatively rare, and doesn't affect the DSum much.

In summary, the DSum decreases in the overworld, and increases during a battle, by about 0.5 every frame on average.

Application

The main use of DSum manipulation is to control wild encounters, which depend on both hRandomAdd and hRandomSub:

  • For each step taken in an area with encounters, the RNG is advanced, and if hRandomAdd is less than the encounter rate, an encounter happens.
  • When an encounter happens, the species and level of the wild Pokémon depends on hRandomSub (without advancing the RNG again), with each area having ten "encounter slots":
Encounter slot hRandomSub Range
1 0-50
2 51-101
3 102-140
4 141-165
5 166-190
6 191-215
7 216-228
8 229-241
9 242-252
10 253-255

Since in most areas the encounter rate is not very large, the range of hRandomAdd is already limited. If the DSum is known, then the range of hRandomSub becomes limited too. Therefore, taking steps in the grass only when DSum is in a certain range allows the player to manipulate the likely encounters.

The DSum manipulation can either be used directly, or it can be referred to when searching for more precise RNG manipulation methods to decrease the search space.

External links

  1. RNG manipulation FAQ on Pokémon Speedruns wiki
  2. DSum manipulation FAQ on Pokémon Speedruns wiki
  3. random.asm
This article or section is a stub. You can help Glitch City Wiki by expanding it.