Introduction

A speedrun classic: an accidental crash while routing one category leads to the RTA record in another dropping by a full minute the following week. This movie takes advantage of a miracle in hardware timing and efficiently executes arbitrary code to skip to the end of the game. This submission also reveals emulation accuracy has reached a point where the cycle-sensitive first generation Pokemon games sync with console.

Categories

  • Heavy luck manipulation
  • Heavy glitch abuse
  • Forgoes save data corruption
Used emulator: BizHawk 2.2.2

About the run

Platform choice

This movie uses CGB-in-GBA. The Game Boy Player uses Game Boy Advance hardware and is the preferred platform in the RTA community. It does not sync on Game Boy Color because GBA adds an operation to the bios and the extra cycles offset the random number generator.

Version choice

Blue version is used over Red to save 9 frames in version differences. Blue loses 7 frames to a longer cry from the Pokemon on the title screen, but gains 16 frames from a shorter preset rival name. The glitch used in this route works identically on both versions.

Luck manipulation

The random number generator in Pokemon Blue is delicate. The routine uses the value of a hardware timer to adjust the two bytes used as random numbers, so any slight change in when the routine is run will affect all random numbers from there on. Every input in this movie was produced by a series of scripts that tried variations in movement and delays to find quick setups for lucky situations.

Arbitrary code execution

The glitch

Maps have a list of scripts and an index for which script should run. The map script is run before the joypad is processed in the overworld and before the player blacks out in battle. Basic maps with trainers have three scripts in the list: check if a trainer can see the player, display the text and start a battle, and end the battle. The first two scripts each increment the index and the third zeroes it to have the scripts run in a cycle. When the player talks to a trainer directly, the text increments the index twice in place of the first two scripts.
Wild encounters are rolled before the map script is run. If the player finds then blacks out to an encounter where a trainer will be able to see the player, the map script run then will increment the index before the player warps. The second script will run when the player returns to the map and reference values it expects were set by the first script. Those values can be changed by other events while outside of the map. The only notable value change in this variation is the blackout cleared the flag that indicates the player was seen by a trainer. Trainer text checks that flag to know if the player talked to the trainer directly. Now the second script will display text which increments the index twice before the script increments the index itself and starts a battle.
An index of 4 in Viridian Forest points past the list of scripts and into a list of text. The text at this position contains a control character and inline code to talk to a trainer. The text engine would read the control character then execute the following data as code, but as a map script it is executed as code from the start, and the code interpretation of the character causes the next two bytes to be skipped. This misses the trainer header, or what defines the text data and the flag that indicates if the trainer was defeated. A cleared flag in read-only memory is checked so the code continues, displays invalid text which still increments the index twice, and starts a battle.
Index 6 does the same but with a set flag in read-only memory. No battle starts and invalid, invisible text of a defeated trainer prints when the map script is run. A trainer is talked to manually to increment the index twice. Index 8 points to similar text with inline code to pick up an item, which reads a function address at a position in a list. The position is what is skipped due to the control character, and the invalid position used instead points past the list and into video memory. Video memory is locked when the LCD controller draws the screen and reads will return $FF. The lower byte of the 16-bit address is read in a locked period, but video memory unlocks in the few cycles before the upper byte is read. The actual value in memory is accessible and the resulting address is $F8FF.

The setup

The data at $F8FF is a live copy of working memory. Stored here includes the data for Pokemon in the enemy party starting at slot three, all the original trainer names of Pokemon in the enemy party, the in-game timer values, and the data for Pokemon in the PC. A trainer with three or more Pokemon is never battled so slot three onwards in the enemy party remains full of zeroes.
Enemy party OT names are only seen in link cable trades and the game gets away with the player name there in NPC parties. This leaves two copies of the player name in memory because the most Pokemon in an enemy party at once in the route is two. The player name entered in the intro is "♀:[Mn]a.", where "[Mn]" is the single character. These values correspond to the following assembly:
push af
sbc h
ld [$ff00+c], a
and b
ld a, [$ff00+c]
In-game time at execution is 8:49:23 including frames, or "ld [$1731], sp". This instruction has no effect.
PC data starts with a list of Pokemon in the PC then the data of each Pokemon. The list is structured as Pokemon count, the species of each Pokemon, then a terminator, or $01 $99 $FF here. The relevant values in the data of Bulbasaur are its species again, $99, and the first byte of its original trainer ID, $C9. The ID is generated in the intro. These values correspond to the following assembly:
ld bc, $FF99
sbc c
ret
Below is a trace of the previous assembly. The initial register values are shown and comments highlight the result of the important operations. The code at $07A0 is the middle of a map change function that warps the player to the map in the A register. $76 is the map ID for the Hall of Fame.
; af = $FF20
; bc = $00F0
; de = $3E8D
; hl = $F8FF

push af
sbc h           ; a    = $07
ld [$ff00+c], a
and b           ; f    = $A0
ld a, [$ff00+c]

push af         ; [sp] = $07A0
sbc h           ; a    = $0F
ld [$ff00+c], a
and b           ; cf   = 0
ld a, [$ff00+c]

ld bc, $FF99    ; c    = $99
sbc c           ; a    = $76
ret             ; pc   = $07A0

Route

Intro

  • Text speed is set to FAST and battle animation is set to OFF. It would be 15 frames faster to set options in the overworld, but before new game saves 60 frames by RTA timing to reach sub 10 minutes. This is the only timing method tradeoff in the route.
  • A trainer ID of $C9F7 is manipulated for the arbitrary code execution
  • The player is named "♀:[Mn]a.", where "[Mn]" is the single character
  • The rival is named the preset RED name. It would cost 72 frames to name the rival 1 character and the rival name appears 16 times, so 2 less characters would only regain 32 frames in text at a frame per character. This is evaluated for other names too.

Pallet Town

  • Different music plays in the lab as one of the three audio channels does not advance. This only occurs when a key part of a channel load is split across two frames. It is a stylistic choice to showcase this and three sprite actions are manipulated to line up the operations correctly.
  • Bulbasaur is chosen as the starter Pokemon for a fast rival battle and the arbitrary code execution. It would cost 82 frames to nickname Bulbasaur 1 character but only regain 64 frames. Stats of 19 HP and 9 defense are manipulated to be able to lose the rival battle in three turns.
  • The rival battle is lost because the rewards are not needed. Three 1/39 damage roll scratches with two critical hits are manipulated from Charmander. It is faster to manipulate two tackle misses from Bulbasaur than two 1/256 growl fails even though two fails would be 17 less frames.
  • The player delivers the parcel to Oak as usual. Wild Pokemon in the grass are avoided with manipulation. 15 frames are saved when beside Oak due to less movement from the rival. The rival happens to look down before he leaves the lab and the cutscene takes 2 less frames than expected.

Viridian City

  • A Poke Ball is purchased to catch a level 5 Spearow on Route 22. This time investment pays off in the battles at the end of the route, but a second Pokemon is required to deposit Bulbasaur into the PC anyway. The 1 character nickname for Spearow saves 47 frames.
  • Bulbasaur is deposited into the PC for its data and to lower party count
  • The party is healed to set the blackout location closer than Pallet Town

Viridian Forest

  • A level 5 Pikachu and critical hit are manipulated in front of a trainer
  • The first Weedle is defeated while redbar is obtained. Two 1/39 damage roll critical hit poison stings are manipulated from Weedle. Redbar plays a warning sound and skips delays caused by sound effects, and while the sound is repetitive, its brief use in this route nets 2 seconds.
  • A speedtie win defeats the second Weedle and a critical hit defeats each of the final two Pokemon. On the way to the final fight, there are 10 frames of delay each step due to an invisible textbox with 7 characters. This textbox would cause more delay if the text speed was slower.
  • The arbitrary code executes and warps the player to the Hall of Fame

Noxxa: Judging.
Noxxa: Great to see emulation accuracy improve to the point of console verifying even a notoriously cycle-sensitive game like classic Pokémon. And, of course, it's also great to see the game broken again in yet another creative way to save time, and it's excellently executed too. Accepting as an improvement to the published no-save-corruptions run.
Spikestuff: Publishing.


TASVideoAgent
They/Them
Moderator
Joined: 8/3/2004
Posts: 15577
Location: 127.0.0.1
This topic is for the purpose of discussing #5859: gifvex's GB Pokémon: Blue Version "warp glitch" in 10:12.00
Patashu
He/Him
Joined: 10/2/2005
Posts: 4043
This is amazing! Console verified before even submitted, music glitch in Professor Oak's lab and a hilarious new way to break Pokemon gen 1 faster than ever before. This game never ceases to entertain.
My Chiptune music, made in Famitracker: http://soundcloud.com/patashu My twitch. I stream mostly shmups & rhythm games http://twitch.tv/patashu My youtube, again shmups and rhythm games and misc stuff: http://youtube.com/user/patashu
Editor, Expert player (2073)
Joined: 6/15/2005
Posts: 3282
Oh, nice. I had actually considered making this run (not to such a perfect extent though) when I first saw it on speedrun.com. Good thing I didn't actually work on it (beyond a single test run I made in a couple hours). A bit surprised you were willing to do all this work in a category where every single run is in danger of being completely obsoleted by a single discovery. What's great about this TAS: No save corruption, no item menu corruption (those are way too easy and have been done millions of times before). Instead, just an extremely well-planned glitch that suddenly warps you to the end. And it looks like there was a secret Bug Catcher Hall of Fame in Viridian Forest all along. :D
GJTASer2018
He/Him
Joined: 1/24/2018
Posts: 303
Location: Stafford, NY
FractalFusion wrote:
What's great about this TAS: No save corruption, no item menu corruption (those are way too easy and have been done millions of times before). Instead, just an extremely well-planned glitch that suddenly warps you to the end.
Wonder if that could qualify making it a separate branch (e.g. "no corrupting glitches" or "no memory corruption")...
c-square wrote:
Yes, standard runs are needed and very appreciated here too
Dylon Stejakoski wrote:
Me and the boys starting over our games of choice for the infinityieth time in a row because of just-found optimizations
^ Why I don't have any submissions despite being on the forums for years now...
Fortranm
He/Him
Editor, Experienced player (878)
Joined: 10/19/2013
Posts: 1121
I find it funny that Pikachu, the mascot of the franchise, plays a key role in this run. Yes vote for finally updating this category. Do you plan to make a GSC any% run based on current RTA route?
Spikestuff
They/Them
Editor, Publisher, Expert player (2642)
Joined: 10/12/2011
Posts: 6438
Location: The land down under.
A Console Verified encode ey? And this would be the third GBC-GBA TAS. Only that the prior two actually used the "enhanced" to unlock a hidden character whereas this uses it for simpler verification. Still don't like the "cause RTA community" excuse being the reason it was used, you did expand on it with an actual explanation so whatever. He's my Yes. Here's my claim for Pubs for when it gets accepted. (cause it's Pokemon)
WebNations/Sabih wrote:
+fsvgm777 never censoring anything.
Disables Comments and Ratings for the YouTube account. Something better for yourself and also others.
The8bitbeast
He/Him
Expert player (2633)
Joined: 11/26/2015
Posts: 183
Location: Australia
Great work on this, it's nice to see a TAS with the new glitches and it's very technically impressive. If possible I'd really like to see this published alongside http://tasvideos.org/4416S.html as a seperate branch. I really like that TAS and I feel that it is what the NSC category was originally intended to be like. Furthermore, that TAS did state that a restriction was no warp glitch in the goal choice. That being said, this is still a really interesting category and a very well done TAS. It's nice to see this submitted since it's very relevant for the RTA community. Definite yes vote from me
Former player
Joined: 3/13/2017
Posts: 15
FractalFusion wrote:
Oh, nice. I had actually considered making this run (not to such a perfect extent though) when I first saw it on speedrun.com. Good thing I didn't actually work on it (beyond a single test run I made in a couple hours). A bit surprised you were willing to do all this work in a category where every single run is in danger of being completely obsoleted by a single discovery.
I was behind the routing for what's on SRC and set aside some setups not viable for real-time runs, so most of the work was done then. If a new discovery is found then that's always a good thing. It could be a long time though, trainerfly is still the earliest glitch after save corruption, just now it's used for ACE.
Fortranm wrote:
Do you plan to make a GSC any% run based on current RTA route?
Maybe, but GSC still needs some work done on RTC emulation to sync with console.
Experienced player (504)
Joined: 1/12/2007
Posts: 682
Really interesting run. Thanks for making it. Voted yes.
Skilled player (1040)
Joined: 7/24/2013
Posts: 175
Amazing work, the precision down to individual CPU cycles necessary to make this work is really impressive. I'm happy a setup to exploit the TFly in Viridian Forest to trigger ACE has finally been found, I remember I looked at that a few years ago. I'm not surprised I didn't find anything, seeing now how it works and how it was discovered. Congratulations on this run. Seeing this makes me want to return to this game, but I'm rusty and would need to catch up on a lot of things.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3821)
Joined: 11/30/2014
Posts: 2829
Location: US
Fascinating. I really like stuff like this, working right on the edge of what the hardware can do where accuracy is absolutely required to get it right. And when it comes to edge case ACE runs, my feeling is that it needs to work on hardware or it doesn't count, so having a temp encode of a console verification is a nice touch. Yes vote!
Editor
Joined: 11/3/2013
Posts: 506
So, I was about to comment "looks like one of the audio channels is missing in Oak's lab, better get that cleared up in the final encode." Then I read the submission notes...
Skilled player (1741)
Joined: 9/17/2009
Posts: 4981
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
That's quite an achievement; both the glitch discoveries + managing to sync on console. In the future, would you attempt to tackle the other runs of this game (and maybe even get them to sync on console)? Now I wonder would anyone attempt eventually to make a gameboy TAS on dolphin using gameboy player lol
Former player
Joined: 3/13/2017
Posts: 15
MrWint wrote:
Amazing work, the precision down to individual CPU cycles necessary to make this work is really impressive. I'm happy a setup to exploit the TFly in Viridian Forest to trigger ACE has finally been found, I remember I looked at that a few years ago. I'm not surprised I didn't find anything, seeing now how it works and how it was discovered. Congratulations on this run. Seeing this makes me want to return to this game, but I'm rusty and would need to catch up on a lot of things.
Thank you. I'm happy you got to see it, your submissions set an incredible precedent for luck manipulation.
Moderator, Senior Ambassador, Experienced player (907)
Joined: 9/14/2008
Posts: 1014
Can you please clarify what level of console verification was employed here? Did you use Endrift's GBPP? I'd like to try to follow through on actual verification on console if there's a way to do it. Voted Yes. :)
I was laid off in May 2023 and became too ill to work this year and could use support via Patreon or onetime donations as work on TASBot Re: and TASBot HD is stalled. I'm dwangoAC, TASVideos Senior Ambassador and BDFL of the TASBot community; when healthy, I post TAS content on YouTube.com/dwangoAC based on livestreams from Twitch.tv/dwangoAC.
Alyosha
He/Him
Editor, Emulator Coder, Expert player (3821)
Joined: 11/30/2014
Posts: 2829
Location: US
Something that I think is worth pointing out here is that even though GBC BIOS is used, it is modified internally in Gambatte like so:
	unsigned readBios(const unsigned P) {
		if (gbIsCgb_) {
			if (agbMode && P >= 0xF3 && P < 0x100) {
				return (agbOverride[P - 0xF3] + cgbBios[P]) & 0xFF;
			}
			return cgbBios[P];
		}
		return dmgBios[P];
	}
This changes the last few segments of BIOS execution from this:
00F2:  18 02     JR   00F6h          A:12 B:00 C:00 D:ff E:56 F:c0 H:00 L:0d LY:99 SP:fffe  Cy:12985836
00F6:  CD D0 05  CALL #05D0h         A:12 B:00 C:00 D:ff E:56 F:c0 H:00 L:0d LY:99 SP:fffe  Cy:12985848
.
.
.
00F9:  AF        XOR  A              A:43 B:14 C:00 D:00 E:08 F:c0 H:00 L:7c LY:93 SP:fffe  Cy:13053504
00FA:  E0 70     LDH  (#FF70h),A     A:00 B:14 C:00 D:00 E:08 F:80 H:00 L:7c LY:93 SP:fffe  Cy:13053508
00FC:  3E 11     LD   A,#11h         A:00 B:14 C:00 D:00 E:08 F:80 H:00 L:7c LY:93 SP:fffe  Cy:13053520
00FE:  E0 50     LDH  (#FF50h),A     A:11 B:14 C:00 D:00 E:08 F:80 H:00 L:7c LY:93 SP:fffe  Cy:13053528
0100:  00        NOP 
to this:
00F2:  18 01     JR   00F5h          A:12 B:00 C:00 D:ff E:56 F:c0 H:00 L:0d LY:99 SP:fffe  Cy:12985836
00F5:  CD D0 05  CALL #05D0h         A:12 B:00 C:00 D:ff E:56 F:c0 H:00 L:0d LY:99 SP:fffe  Cy:12985848
.
.
.
00F8:  AF        XOR  A              A:43 B:14 C:00 D:00 E:08 F:c0 H:00 L:7c LY:93 SP:fffe  Cy:13053504
00F9:  E0 70     LDH  (#FF70h),A     A:00 B:14 C:00 D:00 E:08 F:80 H:00 L:7c LY:93 SP:fffe  Cy:13053508
00FB:  04        INC  B              A:00 B:14 C:00 D:00 E:08 F:80 H:00 L:7c LY:93 SP:fffe  Cy:13053520
00FC:  3E 11     LD   A,#11h         A:00 B:15 C:00 D:00 E:08 F:00 H:00 L:7c LY:93 SP:fffe  Cy:13053524
00FE:  E0 50     LDH  (#FF50h),A     A:11 B:15 C:00 D:00 E:08 F:00 H:00 L:7c LY:93 SP:fffe  Cy:13053532
0100:  00        NOP  
The GBA identifier being the increment of B to one. @gifvex: how did this realization come about? I'm not aware of the GBA version of GBC BIOS being dumped. Did this solution just match up to observed behaviour and was simple enough to be correct? (I failed to arrive at this solution when looking over the code myself a couple months back so nice work to whoever came up with that!)
Former player
Joined: 3/13/2017
Posts: 15
dwangoAC wrote:
Can you please clarify what level of console verification was employed here? Did you use Endrift's GBPP? I'd like to try to follow through on actual verification on console if there's a way to do it.
For the topic: I'm in contact with dwango and we'll look to get the console verification replicated at some point.
Alyosha wrote:
@gifvex: how did this realization come about? I'm not aware of the GBA version of GBC BIOS being dumped. Did this solution just match up to observed behaviour and was simple enough to be correct? (I failed to arrive at this solution when looking over the code myself a couple months back so nice work to whoever came up with that!)
Correct, it was a theory by ExtraTricky in 2016 and has held up since. The difference in initial state between GBC and GBA is (1) the b register is 1 higher, (2) the zero flag is reset, and (3) the cycle counter is 4 higher. Most of the accuracy changes came from identifying random number divergence between console and emulator then drilling down the missing or extra cycles.
Post subject: Movie published
TASVideoAgent
They/Them
Moderator
Joined: 8/3/2004
Posts: 15577
Location: 127.0.0.1
This movie has been published. The posts before this message apply to the submission, and posts after this message apply to the published movie. ---- [3655] GB Pokémon: Blue Version "warp glitch" by gifvex in 10:12.00
Skilled player (1741)
Joined: 9/17/2009
Posts: 4981
Location: ̶C̶a̶n̶a̶d̶a̶ "Kanatah"
TiKevin83
He/Him
Ambassador, Moderator, Site Developer, Player (155)
Joined: 3/17/2018
Posts: 358
Location: Holland, MI
I believe it may need to be tweaked slightly to play back on BizHawk 2.2.2 since it's the only version with the necessary accuracy patches.
Player (27)
Joined: 3/2/2014
Posts: 34
Location: Canada
jlun2 wrote:
This is rather late, but I wonder does that mean [3358] GBC Pokémon: Yellow Version "arbitrary code execution" by MrWint in 05:48.28 would be potentially be able to be replicated on console?
BizHawk 2.2.2 does not support subframe inputs, which are used to bootstrap multiple bytes in a single frame from controller input. I'm also not sure how one would go about replaying subframe inputs to a console.
Meerkov wrote:
The human element of the run is far more entertaining than the game itself. If it wasn't for someone lying about their record 40 years ago, I don't think we'd take a second look at this run/game. Meh vote.