(Link to video)
Pokemon Yellow Total Control Hack. Reprogramming the game from the inside!

Game objectives

  • Emulator used: vba-rerecording 23.5
  • Reprogram the Game from the inside

Comments

I've included a detailed writeup here: http://aurellem.org/vba-clojure/html/total-control.html
The following are the highlights:

Introduction

Think of pokemon yellow as creating a little universe with certain rules. Inside that universe, you can buy items, defeat rival trainers, and raise your pokemon. But within that universe, you are bound by the rules of pokemon. You can't build new buildings, or change the music, or change your clothes.. There are some games (like chess), where it is not possible to alter the rules of the game from within the game. No matter what moves you make in chess, you can never change the rules of the game so that it becomes checkers or basketball. The point of this run is to show that you CAN change the rules in pokemon yellow. There is a certain sequence of valid actions (like walking from one place to another or buying items) that will allow you to transform pokemon yellow into Pacman, or Tetris, or Pong, or a MIDI player, or anything else you can imagine.

Background

The speedrun (#2913: p4wn3r's GBC Pokémon: Yellow Version in 01:36.95) by Felipe Lopes de Freitas (p4wn3r), beats pokemon yellow in only 1 minute and 36 seconds. It does it by corrupting the in-game item list so that he can advance the list past its normal limit of 20 items. The memory immediately after the item list includes the warp points for the current map, and by treating that data as items and switching and dropping them, he can make the door from his house take him directly to the end of the game.
When I first saw that speedrun, I was amazed at how fast pokemon yellow could be beaten, and that it was possible to manipulate the game from the inside, using only the item list. I wondered how far I could extend the techniques found in p4wn3r's run.
The gameboy is an 8 bit computer. That means that ultimately, anything that happens in pokemon is a result of the gameboy's CPU reading a stream of 8 bit numbers and doing whatever those numbers mean. For example, in the gameboy, the numbers:
62 16 37 224 47 240 37 230 15 55
mean to check which buttons are currently pressed and copy that result into the "A" register. With enough numbers, you can spell out an interactive program that reads input from the buttons and allows you to write any program you want to the gameboy. Once you have assembled such a program and forced the game to run it, you have won, since you can use that program to write any other program (like Tetris or Pacman) over pokemon yellow's code. I call a program that allows you to write any other program a "bootstrapping program". So, the goal is to somehow get a bootstrapping program into pokemon yellow and then force yellow to run that program instead of its own.
How can we spell out such a program? Everything in the game is ultimately numbers, including all items, pokemon, levels, etc. In particular, the item list looks like:
item-one-id         (0-255)
item-one-quantity   (0-255)
item-two-id         (0-255)
item-two-quantity   (0-255)
.
.
.

Let's consider the button measuring program [37 62 16 37 224 37 240 37 230 15 55] from before. Interpreted as items and item quantities, it is
lemonade     x16
guard spec.  x224
leaf stone   x240
guard spec.  x230
parlyz heal  x55
So, if we can get the right items in the right quantities, we can spell out a bootstrapping program. Likewise, when writing the bootstrapping program, we must be careful to only use numbers that are also valid items and quantities. This is hard because there aren't many different items to work with, and many machine instructions actually take 2 or even 3 numbers in a row, which severely restricts the types of items you can use. I ended up needing about 92 numbers to implement a bootstrap program. Half of those numbers were elaborate ways of doing nothing and were just there so that the entire program was also a valid item list.
The final part of the hack is getting pokemon yellow to execute the new program after it has been assembled with items. Fortunately, pokemon keeps a number called a function pointer within easy reach of the corrupted item list. This function pointer is the starting point (address) of a program which the game runs every so often to check for poison and do general maintenance. By shifting an item over this function pointer, I can rewrite that address to point to the bootstrapping program, and make the game execute it. Without this function pointer, it would not be possible to take over the game.

The Run

Pallet

I start off and name my rival Lp/k. These characters will eventually be treated as items and shifted over the function pointer, causing it to execute the bootstrapping program that will soon be constructed. I start the run the same as p4wn3r's and restart the game while saving, so that the pokemon list is corrupted. By switching the 8th and 10th pokemon, I corrupt the item list and can now scroll down past the 20th item. I shift items around to increase the text speed to maximum and rewrite the warp point of my house to Celadon Dept. Store. (p4wn3r used this to go directly to the hall of fame and win the game in his run.) I deposit many 0x00 glitch items into the PC from my corrupted inventory for later use. Then, I withdraw the potion from the PC. This repairs my item list by overflowing the item counter from 0xFF back to 0x00, though the potion is obliterated in the process. I then take 255 glitch items with ID 0x00 from the computer into my personal items.

Celadon Dept. Store

Leaving my house takes me directly to Celadon Dept. store, where I sell two 0x00 items for 414925 each, giving myself essentially max money. I hit every floor of the department store, gathering the following items:
 +-------------------+----------+
 |##| Item           | Quantity |
 +--+----------------+----------+
 |1 | TM02           |  98      |
 |2 | TM37           |  71      |
 |3 | TM05           |   1      |
 |4 | TM09           |   1      |
 |5 | burn-heal      |  12      |
 |6 | ice-heal       |  55      |
 |7 | parlyz-heal    |  99      |
 |8 | parlyz-heal    |  55      |
 |9 | TM18           |   1      |
 |10| fire-stone     |  23      |
 |11| water-stone    |  29      |
 |12| x-accuracy     |  58      |
 |13| guard-spec     |  99      |
 |14| guard-spec     |  24      |
 |15| lemonade       |  16      |
 |16| TM13           |   1      |
 +--+----------------+----------+
After gathering these items, I deposit them in the appropriate order into the item PC to spell out my bootstrapping program. Writing a full bootstrap program in one go using only items turned out to be too hard, so I split the process up into three parts. The program that I actually construct using items is very limited. It reads only from the A, B, start, and select buttons, and writes 4 bits each frame starting at a fixed point in memory. After it writes 200 or so bytes, it jumps directly to what it just wrote. In my run, I use this program to write another bootstrapping program that can write any number of bytes to any location in memory, and then jump to any location in memory. This new program can also write 8 bits per frame by using all the buttons. Using this new bootstrap program, I write a final bootstrapping program that does everything the previous bootstrapping program does except it also displays the bytes it is writing to memory on the screen.

Finale

After completing this bootstrapping program, I go to the Celadon mansion, because I find the metaness of that building to be sufficiently high to serve as an exit point for the pokemon universe. I corrupt my item list again by switching corrupted pokemon, scroll down to my rival's name and discard until it is equal to the address of my bootstrapping program, and then swap it with the function pointer. Once the menu is closed, the bootstrapping program takes over, and I write the payload....

Other comments

The entire video was played by the computer using bots. I used functional programming to write search programs over different possible game states to find the most efficient way of performing general actions. Some interesting things I developed but didn't use were pretty printing functions to display the game's internal data structures, and an "improbability drive" that forces improbable events to happen automatically using search.
Here are a few example scripts:
 (defn-memo viridian-store->oaks-lab
   ([] (viridian-store->oaks-lab
        (get-oaks-parcel) ) )
   ([ script \]
      (->> script
           (walk [↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
                  ← ← ← ← ← ← ← ← ← 
                  ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
                  ← ←
                  ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
                  ↓ ↓ ↓ ↓ ↓ ↓ ↓
                  → → → → → → → →
                  ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
                  ← ← ← ← ←
                  ↓ ↓ ↓ ↓
                  ])
           (walk-thru-grass
            [↓ ↓ ↓ ↓ ↓ ↓ ↓])
           (walk [↓ ↓ ← ↓ ↓ ↓ ←
                  ↓ ↓ ↓ ↓ ↓ ↓
                  → → → ↑])
                 
           (do-nothing 1) ) ) )
This script walks from the Viridian City pokemon store to Oak's Lab in the most efficient way possible. The walk-thru-grass function guarantees that no wild battles will happen by manipulating the game's random number generator.
 (defn-memo hacking-10
   ([] (hacking-10 (hacking-9) ) )
   ([ script \]
      (->> script
           begin-deposit
           (deposit-held-item 17 230)
           (deposit-held-item-named :parlyz-heal 55)
           (deposit-held-item 14 178)
           (deposit-held-item-named :water-stone 29)
           (deposit-held-item 14 32)
           (deposit-held-item-named :TM18 1)
           (deposit-held-item 13 1)
           (deposit-held-item 13 191)
           (deposit-held-item-named :TM02 98)
           (deposit-held-item-named :TM09 1)
           close-menu) ) ) 
 
This script calculates the fastest sequence of key presses to deposit the requested items into a PC, assuming that the character starts out in front of a computer.

Other Comments

The final payload program is multiple programs. I created a reduced form of MIDI and implemented it in gameboy machine language. Then I translated a midi file from [dead link removed] into this reduced MIDI language. The payload program contains both the music data and the MIDI interpreter to play that data. The picture works in a similar way. There is code to translate a png file into a form that can be displayed on a gameboy, and other code to actually display that image. Both the image and the display code are also written by the final bootstrapping program. Even though my final payload is rather simple, you can write any program at all as the payload. The source for the sound and image displaying code is at http://hg.bortreb.com/vba-clojure
This entire project is open source and I encourage anyone who wants to take the code and play around!

Suggested Screenshots

Or whatever you all think would be best.
I encoded the video with/without button visualization here:

FractalFusion: Replaced movie file to fix time (note that the parser works in such a way so that the time listed for a VBM can easily be faked).
FractalFusion: Response is well-received for the new concept. Accepting for publication.
natt: Processing...
FractalFusion: Changed branch to "Executes Arbitrary Code".

1 2
5 6 7 8
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
I second the suggestion for the category name "executes arbitrary code". This is the standard term for this kind of exploit when it happens in modern computer systems, and it spells out exactly what is being done. I think this term is clearer than "total control". Edit: Here is a wikipedia article on the term: https://en.wikipedia.org/wiki/Arbitrary_code_execution
Wikipedia wrote:
It is the worst effect a bug can have because it allows an attacker to completely take over the vulnerable process. From there the attacker can potentially take complete control over the machine the process is running on.
Former player
Joined: 9/3/2012
Posts: 40
Location: boston
"Executes Arbitrary Code" seems to me like a better name than "Total Control Hack" as well. However, I am worried that "Executes Arbitrary Code" might not be meaningful to those TAS viewers without a computer science background.
Site Admin, Skilled player (1236)
Joined: 4/17/2010
Posts: 11268
Location: RU
Battletoads also allow to hack the main pointer, stick it to SRAM open bus (toads have no sram) and execute arbitrary code that was left from the last relevant RAM address. In some cases it rolls through the undefined code until reaches the game end routine. Requires crazy planning. But FCEUX 2.2.0 allows aweosme debug tools to work on that thing. Post #326882
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
AnS
Emulator Coder, Experienced player (723)
Joined: 2/23/2006
Posts: 682
Battletoads doesn't have enough means to write any coherent sequence of code (no buffer overflow, just wild pointers and objects manipulation, producing rather erratic way of memory corruption), so the horizon of opportunities is not the same. But then, Battletoads allows memory corruption without using Reset, which is kinda more pure. Anyway, these two TASes are very different. I also support "Executes Arbitrary Code", which is rather modest, but that's good, because the shown result (the picture and music) is not as extremely mindblowing as it could be in theory. So, while I think this movie should get a Star, I wouldn't try to oversell it by calling with pathos-filled names like "Total Control" or Matrix-related stuff.
adelikat
He/Him
Emulator Coder, Site Developer, Site Owner, Expert player (3598)
Joined: 11/3/2004
Posts: 4738
Location: Tennessee
AnS wrote:
I also support "Executes Arbitrary Code", which is rather modest, but that's good, because the shown result (the picture and music) is not as extremely mindblowing as it could be in theory. So, while I think this movie should get a Star, I wouldn't try to oversell it by calling with pathos-filled names like "Total Control" or Matrix-related stuff.
I agree with all of this; including the suggestion of it being a star
It's hard to look this good. My TAS projects
Joined: 3/27/2010
Posts: 32
Reminds me of the computer built in Minecraft which could run Minecraft. Just kidding.
Former player
Joined: 1/17/2006
Posts: 775
Location: Deign
so if we suppose this would work on console verification, would the game cartridge be irreparably damaged or does it fix at reset?
Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign aqfaq Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign Deign
Player (131)
Joined: 5/21/2012
Posts: 74
Location: Cary, NC
jimsfriend wrote:
so if we suppose this would work on console verification, would the game cartridge be irreparably damaged or does it fix at reset?
The system hardware isn't physically capable of changing the ROM data. I'm really surprised this hack works at all, I would have thought these systems would restrict execution to addresses mapped to ROM data.
Editor, Player (44)
Joined: 7/11/2010
Posts: 1022
Yeah, about the worst you could do doing this on a console would be to trash the save file in such a way that the game crashed on load. The game's program is hardwired-in, what's running here is a separate program written into the game's RAM.
Former player
Joined: 9/3/2012
Posts: 40
Location: boston
Though, you can physically destroy the gameboy's LCD circuits by writing to Video Ram during times other than V-blank. However, I made sure that my program does not do this.
Former player
Joined: 2/19/2007
Posts: 424
Location: UK
AnS wrote:
I also support "Executes Arbitrary Code", which is rather modest, but that's good, because the shown result (the picture and music) is not as extremely mindblowing as it could be in theory. So, while I think this movie should get a Star, I wouldn't try to oversell it by calling with pathos-filled names like "Total Control" or Matrix-related stuff.
Personally, I don't think this run needs to be modest. But I was thinking of "Executes Arbitrary Code" as a general goal which would be possible for other games, and not just a term for this single run. Basically, instead of aiming for the fastest time, such a run would try to impress by totally reprogramming the game, and would be judged in terms of technical merit and entertainment. If that is possible in battletoads or super mario world, then one could make "Executes Arbitrary Code" TASes for them too. Obsoletion could be handled the same way we do for fighting games etc. now, i.e. "is the new run more impressive than the old one"?
Joined: 1/17/2008
Posts: 133
tack me on the list of "executes arbitrary code". Accurate, concise, and amazing.
Dwedit
He/Him
Joined: 3/24/2006
Posts: 692
Location: Chicago
feos wrote:
Battletoads also allow to hack the main pointer, stick it to SRAM open bus (toads have no sram) and execute arbitrary code that was left from the last relevant RAM address. In some cases it rolls through the undefined code until reaches the game end routine. Requires crazy planning. But FCEUX 2.2.0 allows aweosme debug tools to work on that thing. Post #326882
Does open bus really work that way? Some emulators just read back the low byte of the address as the value.
Banned User, Former player
Joined: 3/10/2004
Posts: 7698
Location: Finland
ais523 wrote:
Yeah, about the worst you could do doing this on a console would be to trash the save file in such a way that the game crashed on load.
I apologize for going off-topic, but... If the save file on a real cartridge becomes corrupted in such a manner, is there a way to reset or empty it so that you will be able to run the game?
Editor, Experienced player (608)
Joined: 11/8/2010
Posts: 4012
I also really like "Executes Arbitrary Code" for the branch name.
ALAKTORN
He/Him
Player (99)
Joined: 10/19/2009
Posts: 2527
Location: Italy
Warp wrote:
If the save file on a real cartridge becomes corrupted in such a manner, is there a way to reset or empty it so that you will be able to run the game?
are you specifically asking about GB games? most consoles have a combination of button presses to erase save data, though I’m not sure if the GB does I agree with “Executes Arbitrary Code” btw
Editor, Active player (296)
Joined: 3/8/2004
Posts: 7469
Location: Arzareth
Dwedit wrote:
Does open bus really work that way? Some emulators just read back the low byte of the address as the value.
The CPU bus just returns whatever was last placed there, if no device sets it into a particular value. If you read the PPU, you will not get the open value from CPU's bus, but an open value from the PPU's bus, which has whatever was last written to/read from the PPU's registers (where applicable). What happens in the posted example (Battletoads, NES) is: - The opcode was an absolute indirect jump, which causes a read from RAM, and the read value is $75BD, which puts $75 in the bus. - Opcode is read from $75BD. Nothing is mapped there, so bus value $75 is returned. - $75 is interpreted as opcode (75 75, "ADC $75,x"). Equation $75+x produces $75; RAM address $75 is read, and value $6F is returned. Bus now has value $6F. - Opcode is read from $75BF. Nothing is mapped from there, so bus value $6F is returned. - Value $6F is interpreted as opcode (6F 6F 6F, "RRA $6F6F"). This causes a read from $6F6F, which produces the value from open bus, $6F because nothing is mapped at $6F6F. (It also writes at $6F6F, but I am not sure why the written value $37, or $38, is not placed on the bus. 38 is SEC, by the way. Maybe this emulator does not properly emulate the RRA opcode. If it did, the code would still work but the timing would be different, because SEC takes 2 cycles per byte whereas RRA takes 5 cycles per 3 bytes. 37 37 would be "RLA $37,x", which would read $37 and also write back.) Stable loop ensues, repeated until the end of undefined region.
Joined: 5/11/2012
Posts: 14
ALAKTORN wrote:
Warp wrote:
If the save file on a real cartridge becomes corrupted in such a manner, is there a way to reset or empty it so that you will be able to run the game?
are you specifically asking about GB games? most consoles have a combination of button presses to erase save data, though I’m not sure if the GB does
No such feature exists. You could fix it only by disconnecting the save battery.
Editor, Emulator Coder, Site Developer
Joined: 5/11/2011
Posts: 1108
Location: Murka
"Executes Arbitrary Code" it is then.
Banned User, Former player
Joined: 3/10/2004
Posts: 7698
Location: Finland
natt wrote:
"Executes Arbitrary Code" it is then.
Could it be possible that the tag text links to the "arbitrary code execution" wikipedia article?
Demon_Lord
He/Him
Joined: 2/20/2011
Posts: 80
Location: Chicoutimi, Qc, Canada
Warp wrote:
ais523 wrote:
Yeah, about the worst you could do doing this on a console would be to trash the save file in such a way that the game crashed on load.
I apologize for going off-topic, but... If the save file on a real cartridge becomes corrupted in such a manner, is there a way to reset or empty it so that you will be able to run the game?
I don't know about the old GB, but it was a Nintendo requirement that the game must be tolerant to save game corruption on the DS (earliest handheld I worked on), otherwise it wouldn't get release approval. Now, if the save game manages to get an accurate checksum in a corrupted state, I wouldn't have much hope, especially if it's a Flash-based technology without a battery to pull out.
Joined: 2/14/2012
Posts: 73
natt wrote:
"Executes Arbitrary Code" it is then.
Yay :)
Emulator Coder, Skilled player (1141)
Joined: 5/1/2010
Posts: 1217
Warp wrote:
Could it be possible that the tag text links to the "arbitrary code execution" wikipedia article?
Wouldn't be easy, would require nontrivial (or very very hacky) site code changes.
Site Admin, Skilled player (1236)
Joined: 4/17/2010
Posts: 11268
Location: RU
Just put that link to the pub description.
Warning: When making decisions, I try to collect as much data as possible before actually deciding. I try to abstract away and see the principles behind real world events and people's opinions. I try to generalize them and turn into something clear and reusable. I hate depending on unpredictable and having to make lottery guesses. Any problem can be solved by systems thinking and acting.
Mitjitsu
He/Him
Banned User, Experienced player (532)
Joined: 4/24/2006
Posts: 2997
adelikat wrote:
AnS wrote:
I also support "Executes Arbitrary Code", which is rather modest, but that's good, because the shown result (the picture and music) is not as extremely mindblowing as it could be in theory. So, while I think this movie should get a Star, I wouldn't try to oversell it by calling with pathos-filled names like "Total Control" or Matrix-related stuff.
I agree with all of this; including the suggestion of it being a star
I think a moon would be more appropiate. This is like completing every NES game using 1 input. Its a great technical achievement, but not fun to watch. When I rewatch the run, I usually skip the first 10 mins to see the worthwhile part of it.
1 2
5 6 7 8