Wave

Generation 3 of Pokémon is held together by duct tape and I can prove it

Forbidden Tempura

The problem space

Pokémon is a franchise that needs no introduction. Millions upon millions of people have had some exposure thereto. I would like to focus on one tiny implementation detail of the games that formed the third generation of Pokémon: Ruby, Sapphire, FireRed, LeafGreen, and Emerald.

In this generation of the games, the developers of the series first started trying to discourage cheating. To understand what they did, I first need to introduce a few concepts.

  • A Pokémon is an individual member of a Pokémon species. Think of it like a specific individual, just like how there is a sheep that you encounter and there is the species of sheep, of which the aforementioned individual of a member.
  • Every Pokémon has a 32-bit personality value (also commonly called personality ID or PID for short).
  • A (Pokémon) trainer is a concept in the games: Trainers go around and make their Pokémon fight against other Pokémon. They hold contests to find out who is the strongest trainer. Supposedly, these little creatures like beating each other until they faint. The player in the games is a trainer.
  • A trainer identifier (trainer ID) is a 16-bit number that is assigned to every player. There is also another 16-bit number (a secret ID) that is not shown to the player, used to distinguish between identical trainer names with identical trainer IDs. Non-player character trainers generally do not have trainer IDs, but for in-game Pokémon originating from other trainers, Game Freak assigned some.
  • A player can have multiple Pokémon in their party, up to six Pokémon namely.

The studio of the developers of the games (Game Freak) do not want people to cheat. Usage of cheating devices like the GameShark ran rampant. A GameShark would normally accept codes that manipulate memory addresses while the game ran. You can think of a GameShark code like compiled binary code that the GameShark would interpret at runtime to make the desired modification at runtime. This would allow players to alter the information about their Pokémon. One crucial aspect of developing anti-cheating solution is to limit visibility into the goings-on in memory. If a cheat author cannot see what to change, they cannot make a cheat. Game Freak therefore turned to (crude) encryption and checksumming.

The Pokémon structure

The structure of a Pokémon is fairly complex. I will therefore be presenting a simplified model:

struct Pokemon {
    uint32_t pid;
    uint32_t trainerId;
    /* [...] */
    uint16_t checksum;
    /* [...] */

   uint32_t encryptedRegion[4 * 3];
};

The pid field contains the personality ID. This is generated at random when the Pokémon is first created and stays static throughout the existence of a Pokémon.

The trainerId field contains the trainer secret ID in the upper 16 bits and the trainer ID that is actually displayed to the user in the lower 16 bits.

The checksum contains a checksum over the decrypted values of the encryptedRegion.

The encryptedRegion consists of four separate structures that are decrypted on the fly every time the game needs to read or write data located therein, such as the current amount of experience points or the species of Pokémon. The order of the data is shuffled in 24 different ways depending on the personality ID.

Encrypting and checksumming

The encryption is primitive: Every 32-bit word in the encryptedRegion is bitwise exclusive-or'ed with the pid and trainerId fields. This is very fast, but it is also very easy to figure out. The shuffling of the data does more in terms of obfuscation than this encryption does.

In particular, since the output of the encrypted region stays entirely unchanged between two encryptions other than data that changed, it is possible to take a capture of memory before and after changing some information in order to glean information where critical information like experience points are stored, at least for each individual Pokémon. Furthermore, if the plaintext value is known, it is possible to recover the entire encryption key from just one piece of 32-bit information.

Similarly, the checksumming is equally primitive: It is just the sum of all words in the encryptedRegion (in canonical order) truncated to 16 bits. Every time any information in the encryptedRegion is accessed, the game decrypts the Pokémon and first checks the checksum. If it is invalid, the access does nothing and returns a dummy value, plus the Pokémon is marked as invalid.

Paper tape

In Pokémon Emerald, the game frequently queries whether a slot in a party is occupied. It does so by checking the species. If the species is zero, the slot is considered not occupied by a Pokémon. As noted above, the species is actually stored in the encrypted region.

Instead of doing the sensible thing and checking the number of party members, the game actually performs the whole decryption and checksumming process even for a slot that is not occupied to read the species.

An empty slot is a Pokémon struct filled with zeroes. Therefore, the only reason this works is because of how primitive the encryption is: The xor of zero with  is zero. This means that an all-zero encryptedRegion stays zero after decryption because the pid and trainerId values are zero. The checksum also passes because the stored checksum value is zero and the sum of the all-zero decrypted region is also zero.

Conclusion

Game Freak was not very good at obfuscation in 2002 through 2005 and critical functions relied on nasty implementation details of said obfuscation.

About the Author

Forbidden Tempura

I am good at being angry about video games.

Mia Rose WinterReviewer

This might also interest you

My First Game In Godot

Mia Rose Winter 3/7/2024

Last Sunday I decided to finally take a shot at using Godot. I only looked a bit at the getting started section of the documentation but haven't looked at anything past that or even tried using it past myself, past downloading it. As I used many engines before, and tried to make my own, a lot of it was very familiar, but many things were also easier to do than in other engines I know. As I do, I noted in a group chat that I still don't know how to make the 404 page of Wave more interesting, when Nyx suggested “dino minigame but with shork”. As I was a bit kaputt that morning I thought “yea let's go” and opened up Godot. Well, first I needed my main character, so I crudely copied a blahaj design from a sticker Rain gave me a while ago. With that set, I opened up the editor and looked around YouTube and the Godot documentation for all the little pieces of Information I needed. This “Godot 4 Crash Course for Beginners” gave me a good start. In it the c

Game DevelopmentShowcase

Depth Ordering in GameMaker 2

Mia Rose Winter 2/29/2024

At some point during your usage of GameMaker 2 you will very likely encounter a very classical issue in game development, how do I ensure my sprites are drawn in the right order? Anything 2D with movement will still have a sense of hierarchy, some things are in front of others, but how do you do that with GameMaker? When you will look into your trusty search engine, you will most likely find either this blog about using a technique called z-tilting, and if the following doesn't satisfy you, definitely check it out, or you may find the YouTube channel FriendlyCosmonaut with this tutorial video, which is a bit older but still teaches some valid techniques. As someone with more background in different engines and other areas of software techniques, I want to elaborate on some of my strategies to solve this issue, including the one I used in my student project game fairy-strategy, a turn based 2D strategy game. The classic depth = -y The oldest and easiest way to get this working. Things l

Game DevelopmentTutorial

Typeclasses in C

Sara Gerretsen 2/22/2024

(This is a modified version of the pattern shown in this article by Phantz but botched modified into working for my own usecase which I thought I'd document for both others and myself) Motivation I really like making games in C. I'm not sure why, the language just meshes with my brain in a way that I can't get rid of. Using C as a language for games is nice, it basically forces simple, straight to the point solutions. None of the endless abstractions and hierarchies that I've caught myself writing in Rust, C# or C++ (this may or may not be a me problem). General purpose game engines are another problem though. You can make a game with reusable parts, but that's generally not what I'd call a “game engine”. The definition of engine I quite like is that for a framework to be a Game Engine it needs to handle at the very least: Asset Management, Actor/Entity/GameObject lifecycles, Input polling/passing Media (audio, rendering, etc.), And the application loop. While not prescri

Game Development
Powered by Wave