Introduction

Here is a claim that should feel slightly wrong the first time you read it: on an original Game Boy, the list of items in your Pokémon Red bag can be executed as code. Not “interpreted”, not “simulated”. The actual CPU fetches your Potions and Poké Balls, decodes them as instructions, and runs them.

By the end of this article you will understand exactly why that is possible, and you will have walked through the smallest interesting version of it: getting the Game Boy’s CPU to execute one instruction that you chose, planted by hand inside the item bag. We stop the moment that instruction runs. Chaining instructions into a full payload is a separate (large) topic, and the conclusion says a word about where that road leads.

This is, in miniature, a real exploit primitive: a buffer you control, plus a jump into that buffer, equals code execution. The same shape shows up in memory-corruption bugs on modern software. The Game Boy just lets us see it naked, with none of the defenses a 2020s machine would put in the way.

I am assuming you write C, that pointers and memory addresses hold no fear, and that you have met the idea that code and data share the same memory on a von Neumann machine. That last point is the only prerequisite that really carries weight here, because the interesting part is not the fact itself but its consequence, which the next paragraph spells out. Everything else is fair to not know: the Game Boy’s internals, this particular glitch, how exploitation works in general. That is what the article is for.

One practical note before we start. If you only want to read, you need nothing. If you want to reproduce the two demonstrations, and you should, because they are the fun part, you will want a Game Boy emulator with a debugger. The appendix names one, and it takes about a minute to set up.

The one idea to keep in mind

You already know code and data share memory. The consequence we usually forget is this: the CPU never checks which is which. It has a program counter, the program counter holds an address, and the CPU fetches the byte at that address and executes it as an instruction. That is the whole decision procedure. The byte 0x3E is “the number 62” or “the start of a ld a, n instruction” depending on one thing only, and it is not a property of the byte. It is whether the program counter happens to point at it during a fetch.

So the boundary between code and data is not physical. It is drawn entirely by the control flow (where the program counter goes) and by whatever memory protection the hardware enforces. Modern CPUs enforce a lot. The Game Boy enforces none. That gap is the vulnerability this whole article lives inside.

The stage: just enough Game Boy

We need three facts about the machine. No more.

The CPU. The Game Boy runs a Sharp LR35902, an 8-bit processor whose instruction set is close to the Z80. For our purposes it has an accumulator A, some general registers (B, C, D, E, H, L), a 16-bit stack pointer SP, and a 16-bit program counter PC. “Accumulator” is the historical name for the register the CPU privileges above the others: most arithmetic and load instructions read and write A implicitly, so it is where the value being worked on tends to sit. That is why our demonstration instruction targets A, and why inspecting A afterwards is proof enough that it ran.

The program counter. PC holds the address of the next instruction. The CPU fetches the byte there, decodes it, executes it, and advances PC past the bytes it consumed. Jumps, calls, and returns are nothing more than writes to PC. There is no separate notion of “this region is code, that region is data”. PC can hold any 16-bit value, and the CPU will fetch from wherever it points.

The memory map. The Game Boy has a single flat 16-bit address space, 0x0000 to 0xFFFF, carved into regions:

  0000 - 3FFF   ROM bank 0            (the cartridge program, fixed)
  4000 - 7FFF   ROM bank N            (switchable)
  8000 - 9FFF   Video RAM
  A000 - BFFF   Cartridge RAM         (save data, if present)
  C000 - DFFF   Work RAM  (WRAM)      <-- your game state lives here
  E000 - FDFF   Echo RAM              (a mirror of C000-DDFF)
  FE00 - FFFF   OAM, I/O, High RAM, interrupt enable

Note: why does Echo RAM exist? It is not extra memory, and nobody designed it as a feature. The console decodes addresses with fewer lines than the full 16 bits, so the E000-FDFF range physically selects the same WRAM cells as C000-DDFF. Write a byte to 0xD31E and the same byte reads back at 0xF31E: one chip, one byte, two windows onto it. The duplication was an accidental consequence of the hardware design, not an intended programming feature, and Nintendo’s documentation advised developers not to use it.

The part that matters: your Pokémon game state, including the item bag, sits in Work RAM, and Work RAM is readable, writable, and, crucially, executable. There is no memory management unit, no privilege level, no per-page “no execute” bit. Nothing anywhere on this machine says “the program counter is not allowed to point here.” If PC lands at 0xD31E, the CPU fetches from 0xD31E and runs it, exactly as it would from ROM.

Note: why “no execute” is even a thing. On a modern OS, writable pages are marked non-executable (this is DEP / NX, a form of W^X: write XOR execute). Jump into a buffer you just wrote and the CPU faults. The Game Boy predates all of that by decades, so a byte you can write is a byte you can run. Hold onto this contrast; it comes back in the conclusion.

That is the entire stage. Three facts: the CPU blindly follows PC, WRAM holds our data, WRAM is executable. Now we go get a buffer we control.

Step 1: the item bag is writable memory

The Pokémon Red item bag is not a special structure. It is a small, well-known stretch of Work RAM. From the pokered disassembly we know its layout exactly:

Address Meaning
0xD31D item count
0xD31E item 1 - ID
0xD31F item 1 - quantity
0xD320 item 2 - ID
0xD321 item 2 - quantity
0xD322 item 3 - ID
0xD323 item 3 - quantity
… …
0xD344 item 20 - ID
0xD345 item 20 - quantity
0xD346 0xFF end-of-list marker

So the bag is a count byte followed by twenty slots, and one slot is one item: two consecutive bytes, an ID byte and then a quantity byte. Slot 1 is the pair 0xD31E-0xD31F, slot 2 is 0xD320-0xD321, slot 3 is 0xD322-0xD323, and so on until the 0xFF that closes the list. Forty bytes of ID-and-quantity in total, all of it in executable WRAM. Fix that “one slot, two bytes” convention in your head now, because Step 2 plants an instruction across exactly one such pair.

You can verify this yourself in about a minute. Load a save in an emulator with a debugger, open a memory view, and jump to 0xD31E. Now, in the game, look at your first item. Say slot 1 holds Potion x5. The byte at 0xD31E is the Potion’s item ID, and the byte at 0xD31F is 0x05. Toss one Potion so you have four, and watch: 0xD31F changes from 0x05 to 0x04. Buy a fifth, and it goes back to 0x05.

That is the whole point of Step 1. The quantity shown in the menu and the byte in RAM are the same thing. Every time you use, buy, toss, or reorder an item, you are editing bytes at known addresses. The bag is a memory editor with a friendly UI. It is a buffer, and you control its contents.

Note: quantities go further than the menu admits. Normally a quantity is 1 to 99. Through the item-underflow glitch (see the appendix), quantities can be forced to any value from 0x00 to 0xFF. That matters, because it means the quantity bytes can hold any byte we want, which is exactly what we need in the next step. For now, just note it is possible; the mechanism is a rabbit hole of its own.

Step 2: planting your bytes

We have a buffer in executable memory whose contents we can set. Now we decide what to write.

Remember the one idea: those forty bytes are only “item data” because nothing has pointed the program counter at them. If we can get PC to arrive there, the CPU will read the same bytes as an instruction stream, walking straight across the (ID, quantity) pairs without any idea that a boundary was ever supposed to exist. The “item ID / quantity” structure is a fiction maintained by the item menu code, and the CPU is about to ignore it completely.

So let us choose an instruction. Something small, unambiguous, and easy to see land. I will use:

3E 2A     ld a, $2A      ; load the value 0x2A into register A

0x3E is the opcode for “load an 8-bit immediate into A”, and the next byte is that immediate. Two bytes, one instruction, one visible effect: after it runs, register A holds 0x2A. If we see A become 0x2A, we know our instruction ran and nobody else’s did.

Now encode it as items. One fact has to be borrowed from Step 3 to do that: 8F is a glitch item, and using it makes the CPU jump into the item bag. Where it lands is not our choice. The address falls out of the glitch itself, and with the standard setup it is 0xD322, the ID byte of slot 3. So that is where the instruction has to go, whether we like it or not:

Address Byte As an item As code
0xD322 0x3E item 3 - ID ld a, $2A (op)
0xD323 0x2A item 3 - quantity (= 42) ld a, $2A (imm)
0xD324 0xC9 item 4 - ID ret

Concretely: give item slot 3 an ID byte of 0x3E and a quantity of 42, and give slot 4 an ID byte of 0xC9. That is it. You have hand-assembled ld a, $2A ; ret out of nothing but a shopping list.

Which answers the obvious question about the first two slots: we do not use them for anything, and we could not have started the instruction earlier even if we wanted to. Execution begins at 0xD322 and moves forward, so the four bytes of slots 1 and 2 sit behind the program counter and are never fetched. Slot 1 is where 8F itself normally sits, and slot 2 can hold any ordinary item you like. They are not part of the payload; they are just below the landing site.

Note: how you actually pick the items. You do not memorize opcodes as item names. The community keeps tables mapping every byte value to the item it represents, and quantities (0 to 255, thanks to the previous note) give you free bytes directly. In practice you look up which item has ID 0x3E, put it in slot 3 with quantity 42, and give slot 4 the item whose ID is 0xC9. The lesson underneath the bookkeeping: an opcode and an item ID are the same byte wearing different labels.

The ret on the end is housekeeping. Once our chosen instruction has run, we want the CPU to return cleanly to normal game code instead of stumbling forward into whatever bytes come next and crashing. It is not part of “the instruction we chose”; it is the safety net that lets us stop on our terms.

Step 3: the jump

We have a controlled buffer with our bytes in it. The last piece is getting the program counter to point at 0xD322. This is the jump, and it is where the 8F item earns its reputation.

Note: what is 8F, exactly? An item that was never supposed to exist. Item IDs in Red and Blue are a single byte, so there are 256 possible values and far fewer real items; 0x5D is one of the unused ones. Ask the game to display it and it reads character tiles from past the end of the item-name table, which on the English releases renders as the garbled string “8F” (other localisations show something else entirely, which is why you will see this item under different names depending on the region). It cannot be obtained in normal play; the appendix covers where it comes from, and how to skip that entirely by placing it in your bag with an emulator.

When you select a normal item and choose “use”, the game looks up a function pointer for that item’s field effect and calls it. 8F has none, so the lookup runs off the end of the intended table and produces a garbage pointer. That pointer resolves into Work RAM, and the CPU jumps there. In other words, using 8F sets PC to an address inside the RAM block that holds your Pokémon and item data. With the standard setup, execution slides down through some harmless leading bytes and arrives at the start of your item list, right at slot 3, where we planted ld a, $2A.

Read that again, because it is the entire exploit in one sentence: selecting an item causes the program counter to jump into a buffer whose contents you wrote. Controlled data plus a controlled jump into it equals controlled execution.

Let us watch it happen rather than take it on faith. In an emulator debugger:

  1. Set the item slots as in Step 2 (slot 3 = 0x3E / qty 42, slot 4 = ID 0xC9), and have 8F in your bag.
  2. Put an execution breakpoint at 0xD322, the address of our first planted byte.
  3. Note the current value of register A. It will be some ordinary game value, definitely not 0x2A.
  4. Open the bag and use 8F. The breakpoint trips. The debugger stops with PC = 0xD322, sitting on the byte 0x3E, about to fetch it as an instruction. This is the moment the fiction collapses: the program counter is now pointing at what the menu still calls “item 3”, and it is going to run it.

Single-step once. The CPU fetches 3E 2A, executes ld a, $2A, and advances PC to 0xD324. Check register A.

It reads 0x2A.

That value is there because the CPU executed an instruction we authored, byte for byte, from inside a Pokémon save file. We chose the instruction, we chose where it lived, and we chose the moment it ran. Step forward once more and the ret at 0xD324 returns control to normal game code, and the game keeps running as if nothing happened. Mission accomplished: one chosen instruction, executed and verified.

Conclusion

Everything above rests on the single idea from the introduction. Code and data are the same bytes, and on this machine nothing stops the program counter from treating one as the other. We turned that gap into a concrete capability in three moves: we found a buffer we control (the item bag, Step 1), we filled it with a chosen instruction (Step 2), and we redirected the program counter into it (Step 3, courtesy of 8F). The item menu insisted we were editing an inventory. The CPU disagreed.

We deliberately stopped at one instruction. The natural next question is how you get from ld a, $2A to something that does real work, and the answer is that you keep going: place more instructions after the first, and since the CPU just walks forward through memory, it executes them in sequence. The bag is small, so serious payloads use the early bytes as a bootstrap, a short loader that pulls a larger program in from somewhere roomier (text input, box data, even the link cable) and jumps to it. That is how people beat the game from the item menu, or repaint the screen, or run whole new programs. Same primitive, more of it.

Note: what this looks like on a machine that fights back. Our whole approach was code injection: write new bytes, jump to them, run them. It works only because the Game Boy has no memory protection. On a modern system, DEP / NX marks writable memory non-executable, so the jump-into-your-buffer trick faults instantly. Attackers adapted with return-oriented programming (ROP): instead of injecting new code, they chain together fragments of existing executable code (short sequences ending in ret, called gadgets) to assemble the behavior they want, one return at a time. ROP is more work precisely because injection is off the table. The Game Boy exploit and a modern ROP chain are answers to the same question, “how do I make the CPU run my logic”, separated by thirty years of defenses. Seeing the undefended version first makes the defended one much easier to understand.

If the naked version stuck with you, the appendix is where you go deeper.

Appendix and references

Follow along. BGB is a Game Boy emulator with a solid built-in debugger (memory viewer, breakpoints, single-step, register display). Everything in Steps 1 and 3 is meant to be reproduced there.

Ground truth for addresses and routines. The pokered disassembly (pret’s reverse-engineered Pokémon Red/Blue source) is where the 0xD31D item-bag layout and the item-use code come from. If you want to know why a byte is where it is, it is in there.

The glitch, documented. Bulbapedia’s Arbitrary code execution article and the Glitch City Wiki cover 8F (ID 0x5D), the item-underflow glitch used to obtain it and to force 0x00-to-0xFF quantities, and the exact bootstrap offsets that Step 3 kept at arm’s length. Treat these as recipes; this article was the “why the recipe works” that they mostly skip.

How to obtain 8F. The standard route is the item-underflow glitch: underflow the bag’s item counter to 0xFF, exposing slots that overlay unrelated memory (the “expanded item pack”), then maneuver until one of them reads as item 0x5D and pull it into a real slot. It is fiddly, save-corrupting and version-specific, so if you only want the mechanism above, skip it: in an emulator’s memory editor, write 0x5D into an item-ID byte (say 0xD320, slot 2) with a sane quantity, and 8F is in your bag.

Going further on defenses. For the conclusion’s ROP detour, three next steps, in increasing order of effort. Wikipedia’s return-oriented programming page is the fastest overview of gadgets and chaining. ROP Emporium is the practical route: a series of challenges built to teach ROP in isolation, with a beginners’ guide, so you assemble chains yourself instead of reading about someone else’s. And Hovav Shacham’s 2007 paper The Geometry of Innocent Flesh on the Bone is the original systematic treatment, the one that showed gadget chaining is Turing-complete on x86. The primitive is identical to ours; only the obstacle course changes.