Jump to content

Luck manipulation (Generation I): Difference between revisions

→‎Overworld: I think I meant "step" instead of "frame".
>Bbbbbbbbba
(Live and learn...)
(→‎Overworld: I think I meant "step" instead of "frame".)
 
(3 intermediate revisions by 3 users not shown)
Line 1:
{{incomplete}}
 
Pseudorandom number generation in {{RBY}} 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.
 
Line 26 ⟶ 24:
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 the 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.
Line 36 ⟶ 34:
 
==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:
Line 47 ⟶ 45:
* A change of rDIV between the two reads is comparatively rare, and doesn't affect the DSum much. <!-- TODO: Estimation of frequency? -->
 
In summary, '''the DSum decreases in the overworld, and increases during a battle, by about 0.5 everyper frame on average'''.
 
===Application===
Line 58 ⟶ 56:
|-
|
{| class="wikitable"
{| border=1 width="100%" align=left style="background:#f0f0f0; border:1px solid #000000; border-collapse:collapse;"
|-style="background: silver;"
! Encounter slot !! hRandomSub Range
|-
Line 87 ⟶ 84:
 
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.
 
==Hard-reset RNG manipulations==
Most random events in the game depends only on hRandomAdd, which changes rapidly each frame, so manipulation of those events needs frame-level precision. Since it is impossible in real-time gameplay to do all inputs in a playthrough frame-perfectly, those manipulations usually begin by saving the game and hard-resetting the console, in order to reset the state of the RNG.
 
Even doing frame-perfect input for a short period of time may seem impossible at first. However, the key is that the game doesn't accept inputs on all frames. If the player holds down a button before the game begins to accept it, then it will be accepted on the first frame the game does, essentially becoming a frame-perfect input. This technique is known as "buffering" an input in the speedrunning community.
 
A factor that cannot be controlled in RTA, even with a hard-reset and perfect inputs, is the in-game timer (IGT), which goes into the save file. It is in an hours/minutes/seconds/frames format, and is advanced every frame. A carry from the "frames" byte to the "seconds" byte incurs a rather large delay of 72 cycles (or larger if there are also carries on higher bytes, but that's relatively rare). In Red and Blue, the IGT is increased after the RNG advancement every frame, but it can still affect the RNG if it precedes an in-game RNG call or if it slightly changes the timing of a VBlank. In Yellow, the IGT is increased before the framely RNG advancement, resulting in a larger effect. Manipulation failures due to a bad value of IGT is usually referred to as an "IGT0" failure.
 
Most manipulations used in RTA are found by brute-force searches. The search space consists of inputs with large frame windows, some of which are detailed below. The 60 possible value of IGT frames are enumerated in order to determine the success rate of each manipulation.
 
===BIOS===
Generation I Pokémon RTA usually are done on the GBA platform (or an emulation of it), with the Game Boy Color BIOS. The BIOS provides some RNG manipulation opportunities, because it accepts inputs to change the color palette. This subtly affects the timing of the V-Blank interrupts, changing the progression of the RNG.
<!-- TODO: common techniques and their effects (i.e. how subtle).-->
 
===Intro===
It takes at least two inputs from a hard-reset to continue playing a saved game: One to open the title menu from the title screen, and one to select "continue". Furthermore, for the purpose of speedrunning, it's desirable to skip the long intro animation. The most common technique to get through the intro is:
* When the copyright screen appears, hold Up + Select + B. This skips the Game Freak animation completely, and the Gengar vs. Nidorino (Red) / Jigglypuff (Blue) fight animation at the first opportunity.
* When the screen fades to white from the Gengar fight, switch to holding Start. This opens the title menu at the first opportunity.
* When the screen turns white again, switch to holding A. This will continue the saved game at the first opportunity.
* When the title menu disappears and the screen turns white yet again, switch to holding the first overworld input (usually a direction).
 
There are more complex techniques to manipulate the RNG here with humanly possible inputs, but they are generally harder/takes more time than RNG manipulation with overworld inputs, so they are only used in specific cases (e.g. when manipulating the trainer ID, for which there is no opportunity for overworld inputs).
 
===Overworld===
This is the main component of most manipulations. For the purpose of keeping up frame-perfect inputs, the player should be constantly walking, which also manipulates the RNG slightly compared to staying put. At the beginning of each step, the tilemap is updated so that the new row or column that appears on the screen is displayed properly, which delays the framely RNG advancement slightly. The time delta is either 8.1875 (row) or 7.984375 (column) rDIV periods, so a step generally adds 8 to the RNG state (for one time only), but it can be either 9 or 7 depending on the frame on which this happens. Plus, at the end of each step, map loading will cause a "lag frame" where the game doesn't hit a halt instruction before V-Blank, which as mentioned above may slightly affect the RNG too.
 
Another main factor that affects overworld RNG is sprites. The running time of PrepareOAMData depends on how many sprites are visible on the screen (and some static properties of them), which affects the framely RNG advancement. In addition, for sprites currently on screen, the RNG is called to determine the direction the sprite would walk in (even if it cannot actually walk), and the delay until the next movement. This cycle begins when the sprite is first loaded on screen. Notice that the movement state of sprites persists when it becomes off-screen and even after saving and resetting, as long as the player doesn't leave the map. Therefore all manipulations assume that all sprites involved are initially unloaded.
 
The game also checks whether the A and Start buttons are pressed between steps. If the A button is pressed, and if it is not pressed the last time game checks for inputs, the game will take an "overworld frame" (2 frames) to check if the player can pick up a hidden item, which is a technique to delay 2 frames without releasing the directional button. Usually the exact tile on which A is pressed doesn't matter, but it may matter when there are sprites on screen, around the map boundary, or if the effects of a step ends up changing because of the delay.
 
Some manipulations (most notably Mt. Moon manipulations) require the player to actually pick up items. Since item balls are sprites, they must be picked up at the exact frame. Thankfully, the item pickup text box closes without an input, so the player can simply hold the direction to proceed.
 
===Battle===
When a manipulation extends into battle, it's usually to catch the wild Pokémon that has been manipulated to appear. It usually suffices to throw the Poké Ball on the correct frame. The usual procedure is as follows:
* Press A or B to clear the "Wild <Pokémon> appeared!" text box. Release both keys when the text box becomes blank.
* (For Red/Blue) Some time after the "Go! <Your lead Pokémon>!" text (usually during the Pokémon's cry), hold Down + A. This opens the item menu at the first opportunity.
** This makes use of a quirk in the menu UI, where Up + A or Down + A can be handled in the same frame.
** This trick doesn't work in Yellow, because in Yellow the A button has priority. Therefore the player must wait for the cursor to be on "ITEM" before pressing A (a very tight 3 frame window).
* When the menu jingle plays, switch to holding A + B (or A + Up/Left/Right). Assuming Poké Ball is the first item in the inventory, this will throw the ball.
** This makes use of another quirk in the menu UI, where all buttons currently pressed down are checked when ''any'' button is newly pressed.
The most difficult step is the first step, because the window to press A or B is only 4 frames. Mashing a button is not the best way to hit the window, because most people cannot mash at an interval of 4 frames. The recommended technique is to "stagger" an A press with a B press, which effectively extends the window to 8 frames, making it easier to reliably hit with practice.
 
Another argument against mashing is that pressing A or B during a text box may actually affect the RNG slightly. When a text is displaying, holding down A or B will make the game delay only 1 frame between characters, essentially displaying at the "fast" text speed. Although in speedruns the text speed is usually already set to "fast", the game still checks for an input during the 1 frame delay, in a busy-waiting loop. Pressing A or B breaks that loop, and thus has a tiny probability to affect the RNG.
 
Note that the RNG for a successful catch is checked after the "<Player> used Poké Ball!" message is displayed. Therefore the lead Pokémon's name length, species (affects the cry length) and the player's name length all affects the manipulation.
 
==External links==
Line 93 ⟶ 135:
#[https://github.com/pret/pokered/blob/6ba3765c5932996f5da6417ae703794ff10bb1cb/engine/random.asm random.asm]
 
[[Category:Non-glitch exploits]]
{{stub}}
Cookies help us deliver our services. By using our services, you agree to our use of cookies.