SGB Pokémon Red in 41:02.38
Yet one more movie of the first release of the famous Pokémon RPG series. The games of the first generation, most of the time known as RBY, are notable for having a lot of beneficial glitches. Everything that's done in this run can be done by human playing, but most require a lot of luck manipulation and therefore, tool assistance.
This game can be completed in less than one minute of ingame time by abusing save data corruption, but since it changes gameplay completely and is an "artificial" form of glitching, this category was maintained and is often considered the any% completion of the game. This submission improves primo's Blue run under the same conditions by 37 minutes and 55.9 seconds. As far as speedrunning is concerned, Red, Blue and Yellow versions of this game are considered the same game. There's no reason to prefer the Red version, I chose it mainly because of my personal preferences. All movies faster than this submission done in any version under the same conditions should obsolete it.
- Aims for the fastest completion of the game
- Forgoes time saving glitches (save corruption)
- Heavy glitch abuse
- Heavy luck manipulation
- Contains speed-entertainment tradeoffs
Emulator: VBA-rr v19.4
Pokémon RBY is not well emulated by VBA, especially under glitchy circumstances (more specifically the ZZAZZ glitch, which will be explained further). Newer versions tend to randomly crash the game, fill the RAM with strange values and even turn the entire map with wall status (ZZAZZ glitch is well researched nowadays and this behavior is unreported by console players).
All glitches exploited here can be done in any VBA version. I'd love to do the run in a newer version but the emulation inaccuracies could demand several route changes and even require the run to be entirely redone for no reason at all. Since I didn't want to "manipulate" the emulator to work properly, I switched to v19.4, which seems to be the most stable for ZZAZZ. Since validation is essential for this level of glitchiness, the activation of the inventory glitch by means of ZZAZZ (the biggest improvement here) was reported to work on real console by RBY speedrunner Thomaz and was explored by many people at Glitch City Laboratories.
If in doubt about the bugs exploited in this run, refer to FractalFusion's Pokemon game resources article. The important programming errors used here are:
Brock Skip glitch
When talking to the boy in Pewter that stops you from leaving town before you've beaten the gym, it's possible to get past him without facing Brock. By finishing the dialog with B, you can open the menu before walking. After opening it, however, you can't move the cursor. By setting the cursor to SAVE beforehand you can save the game, reset and when the game is loaded again, you can hold right and continue onwards to Mt. Moon.
This one is better known as its weaker form "Mew glitch". That's surely the most important bug in the game, the one that makes possible to complete the pokedex without ever trading and is also a requirement for more devastating glitches. It works like this:
- Find a trainer whose line of sight has the max range.
- Get into his line of sight while he's being entered into the map, since he faces south by default, this gives you enough time to open the menu before he notices you.
- Quickly open the menu and use any warp move (Fly, Dig, Teleport) or an Escape Rope.
- After warping, you can't open the menu or talk to people. To fix this, face another trainer (be sure to have at least one tile of distance so that he walks to you, otherwise the game will lock up).
- Return to the route where you warped from the trainer, a battle with a wild pokemon will start. The species of this pokemon is determined by the special stat of the last pokemon you encountered, its level can be anything from 1 to 13, depending on the last pokemon's attack modifier. A special stat of 21, for example, triggers Mew.
Experience underflow glitch
The experience required for reaching a level and also the exp a pokemon of such level will have when caught is determined by four formulas. Pokemon with fading experience have the formula E = 1.2L³ - 15L² + 100L - 140, where E is the amount of exp points and L the level. Notice that, for levels 0 and 1, this formula yields a negative value. This wasn't supposed to be a problem because no pokemon at level 0 or 1 exist in the wild. However, with Trainer-Fly, it's possible to catch a lv1 pokemon. This is done by using an Attack-reducing move such as Growl on an opponent. Using growl six times takes the Attack modifier from 7 to 1, with Trainer-Fly this generates a Lv1 Pokemon.
Since the game uses a three byte unsigned data to hold the experience, negative experience will make it underflow, giving it millions of exp points. Having a fading experience pokemon at level 1 receive less than 54 exp points will keep its experience at a huge value (more than this amount will make the number overflow back to a small value) makes the game recalculate its level. After this, its level will be set to 100 because of the big amount of experience.
This is another consequence of the Trainer-Fly glitch. In short, what Trainer-Fly does is simulate a battle with a legendary pokemon. Every legendary pokemon in this game can only be fought once, so it has to be removed after the battle starts. The programmers found an interesting way to implement this. Every map has a list of missable objects, they put every legendary in the first position of the list for their respective map and hard coded legendary battles to always remove the first missable object in the list. Additionally, the list of missables is not changed if you enter a map without missables.
This can be exploited to remove Snorlax at east of Vermilion without getting the PokeFlute by doing the following:
- Start the Trainer-Fly glitch.
- Enter the map with Snorlax
- After seeing Snorlax, pass only through maps without missables
- Finish the Trainer-Fly glitch
The method above will start a legendary fight with Snorlax still being at the top position of the missable object list. It'll then disappear.
The bug which allowed the huge improvement. Trainer-Fly mechanics can be used not only to catch pokemon, but to fight Trainers. If it's used with a special less than 200, it'll start a legendary fight with that species of pokemon. A value of 200 or larger instead starts a trainer fight. It's well known that there are pokemon "missingno.s" in the game, but there are also "Trainer Missingno.s", positions in memory accepted by the game as trainers that don't contain anything.
To start a Trainer battle, the game needs to load a lot of data, such as the trainer sprite, his pokemon and the money he'll concede if defeated. When it loads the money is where things can get really ugly. For reasons that are beyond me, money is stored in a completely different manner, the game uses a data structure of three bytes and instead of converting the value to binary, it stores it in "human" representation. For example, $123456 would be stored as 0x123456 instead of 0x01E240, the proper conversion.
Trainer missingno.s of ID 251, 252, 254 and 255 point to location with invalid money data. When the game tries to perform arithmetic with these data in said structure, it goes nuts and starts overwriting huge portions of RAM. More specifically, for every block of three bytes, two of them will contain 0x9999 (the maximum amount of money a trainer could give). This pattern repeats itself many times through RAM. To see this better, I recommend pausing the video on the emulator after the ZZAZZ trainer is faced and set VBA's memory viewer to 0xD070.
The most noticeable effects of this glitch is that your party is turned into Bulbasaurs, many of your pokemon go to level 153, learn Explosion, get poisoned and your name is replaced with something with Z's (that's where the name of the glitch comes from, its discoverer got his name turned to ZZAZZ), this is because all these things correspond to ID 0x99.
To use this to complete the game, some witchcraft has to be made. Having a party of four pokemon, your party will look like this in memory: 4 A B C D 255 0 0 (4 is the quantity, A, B, C, D species ID and 255 marks the end of the party). After ZZAZZ, it'll be: 4 153 153 C 153 153 0 153 See that the party now has nothing to mark its end, what will happen if we deposit a pokemon?
When you deposit a pokemon, the game starts shifting bytes to the left to maintain the data structure. It'll keep shifting bytes until it finds the 255 that marks the end of the party, but now this value is gone! Under special conditions, it's possible to make the first 255 the game finds to be the one that marks the end of the inventory.
For example, an inventory of 3 items is as follows:
3 X1 N1 X2 N2 X3 N3 255 (3 - amount of items, Xi - Id of the i-th item, Ni - quantity of the i-th item, 255 - end) After the shift, it becomes: X1 N1 X2 N2 X3 N3 255 255
Notice that the ID of the first item became the items counter, quantities became IDs and IDs became quantities. The most important stuff is that the items counter can now become an arbitrarily large value. That triggers the Inventory glitch, which has amazed many people at the Yellow submissions.
Inventory Glitch (ZZAZZ variant)
Having the items counter changed allows accessing important parts of RAM and, more specifically, overwriting a warp to the Hall of Fame to trigger the game's end. Because ZZAZZ is very destructive, attempting to toss any item will crash the game immediately, so it can't be done as fast as in the Yellow runs. The only option is to change the pokemon center door to the Hall of Fame via item switching. In this movie, I do some scrolling inside the PokeCenter because doing it outside causes massive lag. Additionally, I do a trick to speed up the text.
The RNG in this game is a TASer's nightmare. Everything affects it, what makes hex editing almost impossible and heightens significantly the complexity of a brute-force algorithm. It uses hardware register entropy, which is not easily emulatable. This makes it very hard to understand its behavior deterministically. Despite attempts from many TASers, some involving disassembly of the ROM, the mechanics of the RNG are still shrouded in mystery.
For this run, I was lucky enough that most of the time the movie synched in v19.4 and v22, so I could use some Lua scripts to brute-force some instances. However, because of an annoying VBA Lua bug, a desync would occur if the bot loaded a savestate, so I had to rerecord manually while it worked.
The 3-step rule
Almost self explanatory, this rule says that wild encounters after a battle can only happen after the player has walked at least 3 steps. That made me waste two steps in this movie.
Addresses 0xFFD3 and 0xFFD4 control most of the randomness in this game. They are updated many times per frame in a way that their sums remains almost constant. This sum was called "D-sum" by primorial#soup. In the overworld, the D-sum slowly decreases and during a battle, it slowly increases.
The important thing to know is that manipulating something that's affected by the two addresses is very difficult, because when one is within the desired range, the other will automatically be in a fixed interval so that the D-sum remains the same. Thus, to manipulate this, it's necessary to get the D-sum to a desired range, but since it doesn't change fast, major frame losses are expected.
Things that are affected by the D-sum are:
- Max critical hits and enemy moves (sometimes when you manipulate a max crit, the enemy will always use a slow move, that was only a problem once in the movie, with a Caterpie, I managed to bypass this losing a lot less than I should have).
- Wild Pokemon Encounters (some seconds have to be waited in order to encounter the species you want with a small amount of steps).
Pallet Town/ Viridian City
At the title screen, I manipulate the Trainer's ID lower byte to be 118. For those who aren't familiar, this is the same as getting the remainder of the Trained ID when divided by 256 to be 118. This is necessary to warp to the Hall of Fame. I pick Charmander and manipulate it to have high DV's. Nothing really special happens after this in this part.
I buy 4 Pokeballs and 2 Escape Ropes, set the cursor to SAVE and walk to the Pewter Boy to perform the Brock Skip glitch. The necessary reset here is done by soft resetting. I did this to make sure I don't corrupt the save data, because the game only soft resets after the saving sequence is completed. Some annoying trainer battles after this and I enter the Pokemon center to set up the warp for the Trainer-Fly glitch that will soon occur.
I Trainer-Fly from the rocket at the last floor and get warped back to the entrance. I face a Youngster and growl his Zubat six times to get a L1 Gengar for the exp underflow glitch. After facing him, I go downstairs, catch the Gengar, do a two-pokemon kill on a L10 Zubat, which gives the necessary experience for Gengar to go to L100. After this, I use Gengar to destroy every trainer and proceed to Cerulean. Since Charmander is slow for the next parts, there were only two good pokemon to consider: L7 Gyarados and L100 Gengar. Published run uses a Gyarados, but here, it sucks because it won't get Bubblebeam from Misty, since the Cascadebadge is not necessary in this run.
I heal at the PokeCenter to set the warp and go north to face Gary and Nugget Bridge. I catch an Abra in the grass to be able to use Teleport (for Trainer-Fly glitch) and visit Bill to be able to proceed to Vermilion. After that, I use an Escape Rope to get back to Cerulean, and defeat the Rocket to get TM28 DIG, having done this, there are only two more trainers to get to Vermilion.
The glitch fest starts. I do Trainer-Fly, face the Gambler and encounter a L11 Drowzee, I manipulate its special stat to be 25 and growl it six times to get a L1 Gastly from the glitch. Having done this, I enter Snorlax's map, go back to vermilion and catch the gastly with Special DV = 9.
I do Trainer-Fly again and get Gastly to L100, it evolves to Haunter and has a special stat of 254, one of the numbers required for the ZZAZZ glitch. There are only two pokemon in the game that can have the ZZAZZ-required special at L100: Haunter and Kadabra. Haunter needed to be glitched as its primary form Gastly because no wild pokemon this early can give a Haunter. Kadabra demanded one additional Trainer Battle to glitch, so it's slower.
Silence Bridge - Hall of Fame
I go through Silence Bridge, facing three mandatory Trainers to reach the grass where Ditto can be encountered. I have Ditto transform into Haunter, acquiring its 254 special stat. Now all requirements for ZZAZZ glitch are fulfilled. I run away, get back to Vermilion and do ZZAZZ.
When the ZZAZZ trainer is encountered, attempting to fight him will make the game crash. The only way out of battle is to throw a pokeball at him (???), at the same time, I switch TM28 into the first slot because its ID is high enough to let me access the necessary portions of memory with the upcoming inventory glitch.
Once the items counter is glitched via depositing, I withdraw a pokemon to restore the end of party byte (this is necessary if you don't want to have an "infinite" amount of pokemon being shown at the Hall of Fame), deposit three pokemon because it's faster than letting their animation play and do the inventory glitch to warp to the Hall of Fame and finish the game.
Mukki: The issue was raised that this run has a similar element to our, shorter, glitched runs, while also displaying a significant change in content to the current any%. While this is true, to publish both would be absurd, as we would be stretching the number of branches for this game arbitralily and on unreasonable grounds. The short run utilises save corruption and it is a very clear goal that the any% does not use it, everything else is good. The categories for Pokémon Generation 1 should be:
- "Dokokashira Door": A glitched run using a glitch specific to the original Japanese release of Pocket Monsters Green. The extreme nature of the glitch allows for a separate category.
- "Save Corruption": Can be used in any of the first generation games. The extreme nature of the glitch allows for a separate category.
- "Any%": Complete the game as fast as possible without using either of the above methods.
- "Gotta Catch 'Em All": Complete the game while also registering all 151 pokémon.
Accepting as an improvement to the currently published run.
sgrunt: I'll handle this one.