Submission #5910: luckytyphlosion's GB Pokémon: Blue Version "Gotta Catch 'Em All!" in 37:55.33

(Link to video)
Game Boy
(Submitted: Pokémon: Blue Version)
Gotta Catch 'Em All!
BizHawk 2.2.2
Pokemon Blue (UE) [S][!].gb
Submitted by luckytyphlosion on 4/1/2018 8:49:28 PM
Submission Comments


  • 100% completion
  • Heavy luck manipulation
  • Forgoes save data corruption
  • Corrupts memory
  • Major skip glitch
  • Heavy glitch abuse

Game Objectives

  • Emulator used: BizHawk 2.2.2
  • Aims for fastest completion time.
  • Catches all 151 Pokémon as quickly as possible.
  •, really, really quickly.
  • Does not modify Pokédex flags
  • Does not use arbitrary code execution.
  • Is really boring.

About the run

Some terms or concepts used in the TAS (such as Cooltrainer) have been explained in the previous submission by MrWint. The justification for platform choice and version choice, and explanation of luck manipulation are mostly the same as the current "warp glitch" submission by gifvex, except that Blue version is used over Red version as it manipulates the required trainer ID faster than Red version, factoring in time lost from Blue version's slower preset player name.


  • Soft reset is pressed 15 times. 16 inputs are required to perform a soft reset and each delays 1 frame. The delays are used to manipulate the trainer ID and allow a soft reset later with just 1 input.
  • A trainer ID of 0xbe05 is manipulated. The bytes are aligned in memory in the expanded item pack where 0xbe is the quantity of some Master Balls and 0x05 is a Town Map item.
  • The player is named the preset BLUE name. The name does not appear enough times before fastest text speed (0 frames per character) is acquired to be worth naming 1 character.
  • The rival is named ",./xox". Each pair of characters corresponds to an item and its quantity in the expanded item pack. The items are TM44 x242, TM43 x183, and BLUE x183. TM44 x242 is merely filler to reduce lag caused by glitched item names, but the TM43 item and BLUE x183 are necessary for the main farming glitch.

Pallet Town

  • Charmander is chosen as the starter Pokemon. DVs (values used to calculate stats) of exactly 0x1024 are manipulated. Charmander has a fast battle for both rival and Weedle.
  • The rival battle is lost because the rewards are not needed. Four 1/256 growl fails from Charmander and three 1/39 damage roll Tackles (+ one non-1/39) from Squirtle are manipulated.
  • Battle animation is ON and saves 30 frames over OFF. The Poke Ball animation costs 10 frames, but each Tackle animation saves 10 frames over a fixed delay when animations are off.

Viridian Forest

  • Options are set in the gate before the forest. Menu speed varies by map and the gate is the best available before Weedle. The menu also skips a 2 frame delay in movement.
  • Weedle is defeated with a combination of four 1/39 damage rolls and four critical hits. Charmander wins the battle with 40/40 Growl PP and 30/35 Scratch PP in order.
  • The cursor is moved to SAVE now because directional inputs are disabled later.

Pewter City

  • An antidote was picked up in Viridian Forest and 5 more items are bought to reach 6 items. Three Poke Balls are used to catch Pokemon and an Escape Rope ends up in slot 6.
  • A trigger causes dialogue with the Brock fan, but the start menu is able to be buffered before the cutscene movement begins. The game is saved and soft reset.
  • After more dialogue, movement is able to be buffered before the trigger catches the player again, and allows the player to pass the Brock Fan before Brock is defeated.
  • The Brock Fan is talked to from the right and invalid cutscene movement data is read that enables walk through walls. The game attempts to find the player's coordinates in memory and load the appropriate data, but (y:16, x:36) is not defined by the game. It finds 0x1024 in Charmander's DVs and loads data from 0x1E28 due to Charmander's move PP.

Cerulean Cave

  • A Ditto is caught and swapped to slot 1. When a transformed Pokemon swaps its first move with a slot it does not have, it will swap move ID 0x00 into the first slot, known as "Cooltrainer".
  • Cooltrainer's invalid name can cause a buffer overflow that copies saved screen data over enemy Pokemon data. This is done to turn a wild Pokemon into MissingNo. and catch it using the screen data saved when opening the party menu. The buffer overflow also sets an audio fade-out value that causes MissingNo.'s Pokedex jingle to be skipped.
  • MissingNo.'s invalid seen flag sets bit 7 of the item quantity in slot 6. The Escape Ropes went from a quantity of 1 to a quantity of 129 and 2 are tossed to unset bit 7.
  • MissingNo.'s Pokedex entry never unsets the flag to flip sprites horizontally. This affects Cooltrainer, so Ditto's summary is viewed because the page unsets the flag.
  • Cooltrainer is activated again with screen data saved when opening the item menu. This MissingNo. catch sets bit 7 again and the Escape Ropes now have a quantity of 255.

Obtaining Item Underflow

Note that the remaining sections make heavy use of the pokered disassembly labels. Each time a new label is mentioned or referenced much later than previous references, the address in square brackets will be listed next to it.
  • Item Underflow is obtained via the "Dry Underflow" method. Escape Rope x43 is created as a side effect to save a quantity toss later.
  • The Use/Toss Menu is brought up to fix the item menu's cursor bounds (set to 1 during Item Underflow), which is currently set so that the cursor can move to at most the second item before scrolling the menu. Not resetting this value would cause the game to render more of item 0x00 (referred to as []j.) which the name lookup causes enough lag to be slower than bringing up the Use/Toss Menu.
  • Escape Rope x43 is swapped into the 9th slot. The 43 (0x2b) represents the lower byte of a pointer used for the main farming glitch.
  • The []j. item below is swapped with a TM43 in the Rival Name Underflow memory section. This forms the pointer 0xf32b, which points to the quantity of the third and last 0xff item (CANCEL).
  • The Options item ([]j. x129) is swapped with the Palette item (Old Amber x0), setting the delay between printing letters to zero.
  • One Master Ball is tossed from Master Ball x3, setting the Last Outside Map warp location to 2, the internal ID of Pewter City.
  • Full Restore x77 is swapped with item 0x7d to reduce lag later on. Item 0x7d belongs to a family of items known as TMTRAINER items, which their names are not properly terminated and read from a backup of the screen tiles, causing considerable lag.
  • []j. x255 is swapped with Moon Stone x10. This sets the source of the value copied to wWalkCounter [0xcfc5] to 0 during the buffer overflow used in the main farming glitch.
  • []j. x1 is tossed from the []j. x255 stack so that the buffer overflow, terminated by 0xff, does not end prematurely.
  • An HM03 is swapped with item 0x9e (4 8 4 8). This does two things: preserves an HM03 for later to be swapped with an unavoidable HM03 x255 that appears when warping to Pewter City, and removes an undesirable TMTRAINER item which would have to be swapped out later anyway to avoid generating lag during the main farming glitch.
  • A Master Ball x4 is swapped out from the game's warp entries and placed in a location that would cause the internal ID of Master Ball (0x01) to be copied to wIsInBattle [0xd057] during the main farming glitch.
  • []j. x1 is tossed from a []j. x0 (corresponding to wEnemyBattleStatus3 [0xd069] for the buffer overflow) to get []j. x255, which sets the end terminator of the buffer overflow.
  • The inventory is wrapped around to reach the start of the inventory, which happens due to the game using 8-bit addition to determine offsets for scrolling menus. Tossing a []j. x0 to reset the cursor to the start of the inventory was found to be slower due to additional lookups of the []j.'s item name.
  • CANCEL x2 is tossed from the third CANCEL's quantity to set it to 0xfe, representing a mart for the game's text ID engine.
  • Exiting Cerulean Cave wrong warps us to Pewter City.
  • Escape Rope x255 is swapped into the map's text pointer. Escape Rope x12 is tossed from Escape Rope x255, giving us Escape Rope x243 which points to 0xf31d.
  • Town Map x255 is swapped with the Town Map generated from the trainer ID to get rid of the 0xff quantity value.
  • The Current Map item is swapped with item 0xae (BLUE), corresponding to Indigo Plateau's Pokémon Center. This allows us to access a PC to change boxes during the main farming glitch, while not generating 0xff bytes upon loading a new map due to a lack of South and East Connections. If the setup was done in an indoor map with no connections, then we would have to toss CANCEL items which is slower as it resets the inventory to the top of the menu.
  • Master Ball x190 (quantity generated from TID) is swapped with Town Map (item ID generated from TID). The item ID of Master Ball corresponds to flags handling print delays, which the whole value requires bit 0 set and bit 1 reset for faster text delay. If bit 0 is reset, then text is forced to display at one frame per character, while if bit 1 is set, then text placed through the "text string" engine (e.g. PC menu options) would be delayed.
  • Master Ball x190 is swapped into a location where its quantity corresponds to wEnemyMonSpecies2 [0xcfd8] for the buffer overflow.
  • The bottom HM03 is swapped with the top HM03 to get rid of the 255 quantities.
  • The player moves to (y:9, x:16), to be able to interact with the now (invisible) sign-turned-mart vendor.
  • With the aforementioned item manipulation, the mart list overflows into other memory regions, allowing us to efficiently catch the remaining 148 Pokémon. Pokémon Storage System boxes are changed every 20 Pokémon (22 for the first round) using the Indigo Plateau PC at (y:07, x:15).
  • Once all remaining 148 Pokémon are captured, all party Pokémon except Ditto are deposited into the PC to save time on the Hall of Fame cutscene.
  • The player walks two steps down to prepare for a fast Hall of Fame warp.
  • TM40 x198 is swapped with Town Map (quantity representing the map ID for the map's north connected map).
  • TM40 x80 is tossed from TM40 x198, giving us TM40 x118, which the quantity corresponds to the Hall of Fame map ID.
  • Parlyz Heal x0 is swapped with HM05, setting the player's y-coordinate to 0 (quantity representing the player's y-coordinate).
  • The player walks up into the Hall of Fame. The two steps down taken earlier were necessary to put the player in a location where the player could walk upwards.

Major Terminology/Concepts

Quantity 255

When the game has to completely remove an item from the inventory, it shifts the items below in order to fill up the empty item slot, until it reaches the end of list terminator (marked as CANCEL). If an item with a quantity of 255 is below the tossed item, then the game mistakes the quantity of 255 for the end of list terminator and stops shifting the remaining items upwards. This leads to interesting side effects such as duplicating the 255 quantity item, or having another item represent the cancel button (despite not actually being the 0xff item). While the former effect makes obtaining the farming setup faster, the latter effect is relevant in obtaining Item Underflow.

Item Underflow/Dry Underflow

When the game merges two same items via swapping, it checks if the on-screen menu needs to be resized (note that this only refers to the current four items shown on screen). If the resulting list length is one, then the menu should be resized to 01 (only being able to use the first item). However, if a merge was somehow accomplished so that the resulting list length is zero (or any other value), then the menu is not resized. In normal gameplay, this does not matter as it is impossible to merge two items with only one item in the inventory. However, by having a non-CANCEL item act as the cancel button, we can merge two items together while having only one item in the inventory. By doing this twice, we can underflow the number of items in the inventory to 255.

LWA (Lucky Wins Again)

LWA, or "Lucky Wins Again" (poking fun at my successful attempts of finding new ways to break the Gen 1/2 glitched speedruns) is the main farming glitch used to catch the remaining 148 Pokémon in the game. The glitch abuses the capability for a mart to create a buffer overflow. When a mart is loaded, the game copies the list to wItemList [0xcf7b], terminated by 0xff. Therefore if we were to create a mart that has a terminator much later than expected, the copied data would overflow into unrelated memory. By controlling the buffer overflow, we can overwrite five main variables allowing us to catch Pokémon at a very fast rate. These variables are:
  • wEnemyMonSpecies2 [0xcfd8]: Read from when catching enemy Pokémon and is used to determine the resulting Pokémon caught, regardless of other similar variables.
  • wIsInBattle [0xd057]: Writing a value of 1 to this address allows throwing Poké Balls outside of battle.
  • wCurOpponent [0xd059]: Starts a battle if this value is non-zero. Must be kept as zero to prevent battles from being generated.
  • wBattleType [0xd05a]: Indicates if this is a non-standard battle (Old Man battle or Safari Zone battle). Must be kept as zero to prevent thrown Poké Balls from glitching out.
  • wEnemyBattleStatus3 [0xd069]: When a Pokémon is captured, the game sets a flag to indicate not to generate new DVs for the Pokémon. This is done in a very weird way, by setting a flag corresponding to whether the Pokémon has transformed or not, and has a side effect of causing subsequent out-of-battle captures to become Dittos (referred to as "Dittoization", and caused due to an assumption made by the programmers that a transformed Pokémon is a Ditto). Therefore, we want to clear this flag. This was the limiting factor for the efficiency of previous glitches, as the buffer overflow method used could not manage to clear this variable, requiring a battle to be completed (by running away) or a save and reset to happen. As this variable is cleared with the corruption, we do not need to do any additional steps to be able to capture more Pokémon.
Other relevant variables that are affected as a side effect of the buffer overflow:
  • wFontLoaded [0xcfc4]: Bit 0 determines whether font is loaded over the VRAM space for sprite walking patterns. Coincidentally, bit 0 is reset during the corruption, and in normal gameplay this would mean the player is transitioning to a different map via a warp, so the game assumes the LCD is disabled (allowing unrestricted access to VRAM) and directly copies the sprite walking patterns to VRAM. This saves time over if bit 0 was set, as the function to copy to VRAM while the screen is enabled would be called instead, thus wasting 5 frames (1 per sprite) every time the mart is closed.
  • wWalkCounter [0xcfc5]: Stores the remaining about of player sprite advances to perform. Longer values mean waiting more, so naturally we want to set this to zero.
  • wAudioFadeOutControl, wAudioFadeOutCounterReloadValue, and wAudioFadeOutCounter [0xcfc7-0xcfc9]: Writing a non-zero value to wAudioFadeOutControl will cause the game to start fading out audio, from the internal volume of 0x77 to 0x00 (in decrements of 0x11). This has a side effect of skipping sound effects, allowing us to bypass forced waits for certain sound effects, such as Pokémon cries. wAudioFadeOutCounterReloadValue, which reloads wAudioFadeOutCounter whenever it hits zero, is coincidentally loaded with 246 allowing for a fadeout long enough to keep the music playing until a cry is played (which sets volume to 0x33, then to 0x77).
To create this custom mart, text pointer manipulation is used. Firstly, the base text pointer is replaced to be 0xf31d (echo RAM copy of wNumBagItems [0xd31d]). From there, 0xf32f, the location where the Pewter Museum sign would read its text using pointer lookup, is manipulated to 0xf32b, which points to the earliest possible address that we can set up this glitch (anything earlier would require tossing the "CANCEL" item which requires too much preparation). At 0xf32b, we set its value to 0xfe. This causes the game to call the mart code instead, as in the text ID engine the game checks the first byte of the text to see if it matches specific values and does alternate functions based on them. In this case, 0xfe will treat the NPC (or sign) as a mart. By removing any early instances of 0xff, setting the actual terminator much later, and manipulating the expanded inventory pack to align correctly with the destination, we can create a buffer overflow that will desirably corrupt memory according to the above values to efficiently catch Pokémon.

Alternatives considered

  • Setting up another text pointer to bring up Bill's PC: The first iteration of the route had slightly better swaps and less movement, however creating a "fake" PC doesn't work out, as changing boxes from a PC that isn't accessed through the game's "hidden object" code (which also handles PCs) will result in the base text pointer being erroneously overwritten.
  • Using a single ROM based pointer to create the glitched mart: While only requiring the preparation of one pointer instead of two, there are no values in ROM that can represent a suitable pointer for the glitched mart without needing to toss the three CANCEL items at the start of the inventory for the buffer overflow to be successful.

Reasons for rejection

LWA isn't very interesting to watch and becomes boring pretty quickly, but the overall goal (catching all Pokémon) is considered 100% and is thus Vault-able. However, it could be deemed rejectable for not being entertaining enough for Moons and using somewhat arbitrary restrictions for Vault, which aims to go as fast as possible. These restrictions are in particular:
  • Does not modify Pokédex flags.
  • Does not execute arbitrary code.
Other restrictions were self-imposed during the routing of this TAS. These restrictions might not even matter towards fastest completion time as LWA may be the fastest setup anyway, although other setups that do not follow the other self-imposed have not been looked into.
  • Does not use glitches that allow executing arbitrary ROM addresses. Modifying the map script pointer (called every overworld frame) comes close to this as it allows specifying an arbitrary ROM address, but fails to completely cover the entire ROM space as only ROM banks that are used by maps can be executed. It is still not used for this TAS.
  • Does not use glitches that allow writing to an arbitrary destination. The text engine has capability to do this, using the unused command 0x03 to repoint the destination to theoretically any address, then by using the string engine to print text to the specified destination. However, it is unable to write completely arbitrary values as some values are used as "control codes" which do alternate functions that do not result in the byte being written. The invalid mart used in LWA does not fall under this as the destination address of the corruption is fixed, while the source is arbitrarily specifiable.
  • Does not use "mass corruption" glitches. Perhaps the most subjective of the self-imposed restrictions, the TAS forgoes glitches that can cause "mass corruption" (which isn't even well defined) such as party overflow (used in previous RTA speedruns of Pokémon Blue Any% No Save Corruption) or out-of-bounds Pokémon Storage System boxes, which can theoretically be used to write a massive amount of data to WRAM, albeit not entirely chosen arbitrarily. These glitches are forgone because of the general unstability of them, as well as the two mentioned "mass corruption" glitches are not easily manipulable.


  • luckytyphlosion: Coming up with the route for the TAS and creating the LWA strategy.
  • gifvex: Botting the entire TAS and suggesting minor route improvements. He chose not to be listed as an author here, because Pokémon is primarily routing-based and LWA is [luckytyphlosion's] creation.
  • Chivu93: While he didn't participate in the making of the TAS, he improved the LWA strategy by using the Master Ball's quantity for the caught Pokémon instead of originally needing to toss a separate item for each Pokémon.
  • MrWint: Faster menuing techinique used in his "SRAM Glitch" TAS.
  • the pokered disassembly: General massive help in documenting the game's code allowing numerous tricks, including the LWA strategy, to be discovered.
  • BGB: Game Boy emulator with an amazing debugger that helped with routing out the TAS.

Noxxa: Judging.
Noxxa: This TAS spawned an interesting discussion on exactly what levels of glitchiness a run can contain while still being considered a legitimate full completion (catch 'em all) movie. Essentially, this movie sets a quite good example: arbitrary code execution and such glitches are not used, as they would break the point of being full completion, setting Pokémon capture flags through memory corruption is not counted (and isn't done), and the movie does run through the game to collect all Pokémon one by one before going to the ending, just like other runs of this category; it just does so more efficiently, cutting out gameplay time between captures and trimming down the capture sequence to its most basic form. Ultimately, it's just full completion to a highly optimized form. As such, this movie is acceptable for the Vault. The rules of the Vault have also been updated as a result of the discussion surrounding this movie, in order to define what levels of glitches are (not) allowed for full completion movies.
Since this movie is much more repetitive in achieving its goal, only relying on one major glitch to collect all Pokémon in one chain, it also can only be accepted in the Vault tier based on entertainment grounds. As such, accepting to the Vault as an improvement to the published "Gotta Catch 'Em All!" movie.
Spikestuff: Gotta Break 'Em All! PUBLISHING!... Wait... that's not how the song goes.
Last Edited by adelikat on 10/25/2023 5:36 PM
Page History Latest diff List referrers