Introduction

Pokemon was a staple of my childhood. I got lost in these games for hours, capturing and training my team of monsters. Beyond the nostalgia, these games also ignited my curiosity for computing. How were these games made? How do they work? How are my Pokemon represented in code, and persisted in between boots of the game? I wanted to answer these questions, for science, and definitely not as an excuse to revisit these games. Let’s dig in.

The Pokemon Data Structure

In Generation I, where the series began in 1998, this 64 byte data structure holds all the data that makes a Pokemon, well, a Pokemon. It contains fields for a Pokemon’s index number, stats, level, status, etc.

The structure is laid out like this (cropped for brevity):Gen I Data Structure Layout

Modelling this data structure in a language like C is trivial:

typedef struct {
  uint8_t index_number;
  uint16_t current_hp;
  uint8_t level;
  uint8_t status_condition;
  uint8_t type1;
  // other fields
} Pokemon;

Of note, there are two fields for level, one at offset 0x03 and the other at offset 0x21. Bulbapedia’s article mentions that the first field, at offset 0x03, is unused. We’ll get to that later.

Analyzing the layout

Knowing how the data structure is laid out, let’s see how this works in practice. Here is a Vaporeon that I have in my game: Vaporeon

Take note of its attributes:

  • No.: 134
  • Level: 25
  • Status: OK
  • HP: 102
  • Type 1: Water

Imagine we can pause the game state and inspect the memory of the game at this very moment. Sameboy, the emulator I am using for this project, provides this feature! According to the article, the data structure for the first Pokemon in our party begins at address 0xD163 + 0x08. Let’s go there and see what we see.

I’ve highlighted the 64 bytes (size of our data structure) at address 0xD16B below. It’s a bit hard to parse, but let’s break it down: Vaporeon's data dump in hex

Offset 0x00: Index Number (1 byte)

The first byte in the data structure, 0x69, is our Pokemon’s index number. Ox69 is 105 in decimal, which is different from the number we see, which is 134. What gives? Well, the internal index number the game uses to identify Pokemon differs from the Pokedex number displayed in-game. This page shows the mapping between index numbers and Pokedex numbers (The first Pokemon ever designed, Rhydon, is index number 1). We can see that Vaporeon does indeed correspond to index number 105, so we know we’re looking at the right data.

Offset 0x01: Current HP (2 bytes)

Here, we see the value 0x0066, which is 102 in decimal, the current HP of the Pokemon.

Offset 0x03: Level (1 byte)

This is the unusual one because there are two fields for level, one at 0x03, and one at 0x21. At both offsets we can see the value 0x19 (25 decimal), so both seem to be accurate. Bulbapedia claims only the value at 0x21 is relevant, so I’m not sure the reason for the redundancy.

Offset 0x04: Status Condition (1 byte)

The status condition byte is interpreted with the following bitfield:

Bit Value Status condition
3 0x04 Asleep
4 0x08 Poisoned
5 0x10 Burned
6 0x20 Frozen
7 0x40 Paralyzed

My Pokemon has status OK, so none of these bits are set, so seeing 0x00 at this offset makes sense.

Offset 0x05: Type (1 byte)

The final field we’ll look at for now is the type byte, which follows this mapping:

# Hex Type
00 0x00 Normal
01 0x01 Fighting
02 0x02 Flying
03 0x03 Poison
04 0x04 Ground
05 0x05 Rock
06 0x06 Bird (unused)
07 0x07 Bug
08 0x08 Ghost
20 0x14 Fire
21 0x15 Water
22 0x16 Grass
23 0x17 Electric
24 0x18 Psychic
25 0x19 Ice
26 0x1A Dragon

Our water-type Pokemon has 0x15, which is the correct mapping.

Writing to our Data Structure

Our Vaporeon is cool and all, but I want my favorite Pokemon, Snorlax. If we could write values to this data structure, could I turn my Vaporeon into a Snorlax without having to go catch one? Sameboy provides this ability as well. Let’s do it!

We’ll craft a Snorlax with these attributes:

  • No.: 143
  • Level: 50
  • Status: Asleep (as he often is)
  • HP: 255
  • Type 1: Normal

For fun, we’ll also make all of his stats 150. I didn’t describe where to find the offset of the stats for brevity, but it’s the same process as the other attributes.

Offset Value (hex) Value (Decimal) Description
0x00 84 132 Snorlax’s index number
0x01 FF 255 Maximum HP
0x03 4 4 Asleep status condition
0x05 0 0 Normal type

After writing these values, the memory layout of our data structure now looks like this: Snorlax's data dump in hex

And the game reinterprets that structure to our desired creature. Neat! Snorlax

Conclusion

By now, we’ve learned how the original Pokemon games interpret memory to display Pokemon and their attributes, as well as how to modify them. The ability to directly modify memory addresses reveals the fundamental relationship between data and gameplay; changing a few bytes can transform a Vaporeon into a Snorlax! This technique has broader implications in gaming: cheating and creating new game content through ROM hacks, to name a few. Most importantly, it demystifies how these classic games work under the hood, bringing clarity to how these bytes come to life.