Introduction
Hi there! In this exciting episode of 'Pokémon Gold: The Game', a young boy named 'A' is going to run around Johto buying and selling items he finds on his journey. Then, he will look in his Coin Case and will make a call to his best friend '999', who will make him a Pokémon Champion without ever fighting the Elite Four.
This run does not aim for the fastest possible time. It was made to show the people that Generation I isn't the only Pokémon game series that can be completed with pure glitches. I am also 100% sure that this run could be significantly improved, since I have no knowledge about how RNG works in Generation II. I was solving all my problems by inserting big amounts of delay between important actions, so that RNG gets a chance to cycle a couple of times. And, since it is my first TAS ever (excluding the tests), I may have made a bunch of obvious mistakes along the way.
Categories
- Heavy glitch abuse
- Heavy luck manipulation
- Forgoes save data corruption
- Low% completion
- Uses a game restart sequence
Emulator/ROM
The movie was recorded on
VBA-RR v23.6 svn480. Since VBA has problems with emulating the Real Time Clock while recording a movie, and correct RTC values are crucial for the run, the RTC emulation was turned off. All other settings were left at their defaults.
I used a standard UE Gold Version ROM found on the Interwebz. MD5: a6924ce1f9ad2228e1c6580779b23878, filename: Pokemon Gold Version (UE) [C][!].gbc
About the run
This run is abusing 3 different programming errors:
1. Pokémon cloning glitch
In order to buy all the items needed, a huge amount of money is required. Thankfully, using the Pokémon cloning glitch to clone a Pokémon holding an item duplicates the item too. So, to get that huge amount of money, 3 Pokémon holding 3 valuable items (Nugget, PP Up, Big Mushroom) are cloned, essentially doubling my amount of cash.
2. Coin Case glitch/glitch dimension
On Pokémon Gold/Silver, there is a popular glitch involving opening the Coin Case after listening to Machop/Machamp's cry. The Coin Case text script is improperly terminated, so the game tries to execute commands past the actual script, leading to arbitrary code execution.
This text script error causes the game to jump to address $E112. By listening to specific cries, manipulating the party Pokémon list and by standing in specific locations on the map, it is possible to redirect that accidental jump to a useful location - I chose my 4th boxed item as a location to store my code (more on that later).
3. Glitched Pokégear numbers
There exist only 36 different numbers a player can hold in their Pokégear contact list. However, the maximum value for a byte is 255, not 36. So there exist (255-36 equals... umm...) 219 numbers with no behavior assigned. Every number has a pointer, which tells the game where to look for the script to execute after calling a number.
All those script pointers are located in a table. Like with the glitch Pokémon in Gen I, requesting a script pointer for a number with ID bigger than 36 will cause the game to read a pointer from a memory area beyond the table. And by sheer luck, the number ID 255 (0xFF) happens to have a script pointer that triggers the Hall Of Fame sequence!
Creating the payload
So the goal of the run is to turn the Coin Case's bad habit of executing arbitrary code into our favor, by causing it to add a glitch person with ID 255 into the Pokégear. Then, by calling that newly added person - we complete the game.
The address $E112, the initial jumping location, is a ECHO RAM section which contains several music/sound related addresses. By playing different sounds and cries it is possible to change the code flow and jump somewhere else. Machop's cry contains a sequence which will redirect the instruction pointer to $EB12.
Now at $EB12, a table of current color palettes is located. By standing in specific areas, it is again possible to redirect the code flow. The grassy area in front of Bill's lab is such a specific area - it contains a jump to $FA98.
After this jump, we're finally located somewhere more useful - in the middle of the third party Pokémon data. This is where the most manipulation potential is. But instead of trying to construct opcodes by catching Pokémon with specific IVs, I decided to use fourth Pokémon's moveset and ID number to create yet another jump to $F61D - 4th item in the PC box. Now, I can construct my own program inside my PC.
The code used to add the person only has to do two different things:
- Add the actual person to the list (write 0xFF to any address between $D9C6 and $D9CF)
- Clean up the stack and return control back to the game
So normally, this piece of machine code should look like this:
ld a,$ff
ld ($d9c6),a
inc sp
ld bc,$0134
push bc
jp $12f5
Sadly, it would be way too easy if it was possible with such a little bit of effort. The opcodes we can use are severely limited by the maximum quantity (99) and the item availability. The real code used to add the glitch ID 255 to the Pokégear is a lot more difficult to understand, and half of it are just elaborate ways of doing nothing, just to pad the opcodes and make them representable as items.
Below is the item list used in the run, and the code it evaluates to.
*** ANY ITEM, ANY QTY
*** ANY ITEM, ANY QTY
*** ANY ITEM, ANY QTY
X Defend x2
TM49 x1
Hyper Potion x5
Burn Heal x7
Fresh Water x1
Surf Mail x79
PP UP x1
TM34 x1
*** ANY ITEM, ANY QTY
Antidote x30
TM28 x1
*** ANY ITEM, ANY QTY
Carbos x1
*** ANY ITEM, ANY QTY
Awakening x29
Blk Apricorn x1
*** ANY ITEM, ANY QTY
Flower Mail x46
TM08 x1
Great Ball x4
Parlyz Heal x10
Big Mushroom x1
*** ANY ITEM, ANY QTY
RageCandyBar x1
*** ANY ITEM, ANY QTY
Flower Mail x51
Surf Mail x51
TM33 x1
*** ANY ITEM, ANY QTY
TM41 x1
inc sp
db $02 ; item filler
pop af
ld bc,$0510 ; [$0510] == 0x4F
ld a,(bc)
rlca
ld l,$01
or l
ld c,a
ld a,$01
ld ($ff00+c),a
ld bc,$0000 ; 0000 - any item, any qty
db $09 ; item filler
ld e,$db
ld bc,$0000 ; 0000 - any item, any qty
dec e
ld bc,$0000 ; 0000 - any item, any qty
db $0c ; item filler
dec e
ld h,e
ld bc,$0000 ; 0000 - any item, any qty
db $35 ; item filler
ld l,$c7
ld bc,$0404 ; [$0404] == 0xFF
db $0d ; item filler
ld a,(bc)
ld d,a
ld bc,$0000 ; 0000 - any item, any qty
ld (hl),d
ld bc,$0000 ; 0000 - any item, any qty
db $b8 ; item filler
inc sp
db $05 ; item filler
inc sp
pop hl
ld bc,$0000 ; 0000 - any item, any qty
jp hl
Hard luck manipulations used:
- Manipulating the trainer ID's high byte to be 0xD6 or 0xF6 (~0.78%)
- Encountering a Paras holding Tinymushroom (~3.75%)
- Encountering a Paras holding Big Mushroom (~1.2%)
- And of course, long continuous critical hit streaks to speed up the battles
Explaining certain steps
At the game's very beginning (first 8 minutes of the game), all actions are delayed on purpose, most noticeably, by continuously mashing the A button, causing the text scrolling to be delayed. For some reason, with insufficient time delay, I wasn't able to successfully get the Coin Case to do what I wanted.
Also, derping on the new game menu at the game start is required to get a proper trainer ID.
While travelling from town to town, I collect every possible valuable item I can find. The real problem with getting all the needed items is the lack of money. So I try to earn as much money as I can, so later only one item duplication round is needed to satisfy my needs.
The real time clock is very important to the trick. If the glitch person 255 is called after the morning has passed, the game would say that 'the number is out of the area'. Also, the lady who gives out TM21 (Frustration) comes only on Sundays.
Special thanks to Sanqui, for discovering the actual arbitrary code part of the coin case glitch.
Noxxa: While this run does well to showcase an arbitrary code execution glitch that can be used to enter the Hall of Fame, there are a number of issues that make it unsuitable for publication:
- It is slower than the current unassisted any% record of 1:22:13 by Werster.
- It is also not optimal for a TAS at some points, e.g. when walking around for a wild Pokémon encounter.
- It also does not conform to the standard of what's considered finishing the game, which is triggering the credits through defeating Red, not through the Hall of Fame. (However, whether this is required for glitched completion may be debatable. Werster's unassisted run also uses major glitches and finishes the game by defeating Red. My personal opinion is that a glitched TAS should trigger the credits through Red.)
For these reasons, I'm rejecting the run for publication. Good luck on your future attempts!