Getting Started with the FireRed Decompilation

 Many years ago, I was a ROM hacker. I never finished a project, not because of the classic "I've started, so I'll not finish" trap that many home projects fall into, but because the ROM is so fragile that doing anything can completely break it and you need to constantly be creating back-ups if you want to progress at all.

I've had my eye on the Pokémon FireRed decompilation project for a while, and a few months ago I decided to get started with it. Unlike ROM hacking which edits the actual game file, the decompilation project is a reverse-engineered code base which can be edited and then built into an actual game. It generally means that there's no need to be constantly creating back-ups (unless, for some reason, source control isn't being used), and it's much easier to change or add completely new features to the game.

To get started, following the Install instructions seemed like a reasonable thing to do.

Step 1. Install devkitARM.

Already done. Too easy. Next.

Step 2. Install some packages.

Error. "These packages do not exist."

I've looked in the package database, and they are definitely there.

"Can't find them."

Right, well I don't actually need them right now, so I'll skip ahead.

Step 3. Clone the pokefirered repository.

Done.

Step 4. Clone a repository with a stupid name, then build it and install it into the pokefirered folder.

It's cloned, but it will not build. And the ROM will not build without it, or the missing packages. I can't find any reasonable solutions.

And so, much like every other time I've encountered a problem with a C or C++ project using devkit that has been caused by a missing package that I've been unable to track down, I gave up.

And, because I'm an idiot who self-harms his mind instead of his body, I came crawling back and tried again. It still couldn't find the packages. I started doing the Community Chang GIF across the internet looking for clues before stumbling onto a tutorial which actually worked.

Thank you, based Lunos.

I told the code to build and it spat out a ROM which booted up successfully in an emulator. I wanted to make some quick changes. Changing the cry on the title screen, or the default names during the introduction seemed like good places to start and so I began looking into them.

Changing the Title Screen Cry

In src/title_screen.c, there were the following lines which define the species to use when playing the cry much further down in the file (PlayCry_Normal).

#if   defined(FIRERED)
#define TITLE_SPECIES SPECIES_CHARIZARD
#elif defined(LEAFGREEN)
#define TITLE_SPECIES SPECIES_VENUSAUR
#endif

Since I was only going to be building one version, I removed the ifdefs that check if the game is FireRed or LeafGreen, and replaced all the code there with just the one line. Instead of using either Charizard or Venusaur, it would use Blastoise (to test this had worked, I had to go and check what Blastoise sounded like).

#define TITLE_SPECIES SPECIES_BLASTOISE

Changing the Default Player Names

This one was a little more involved.

In src/oak_speech.c, there are three arrays of names - sMaleNameChoices, sFemaleNameChoices and sRivalNameChoices. These all determine exactly what they say they do - one lists all random choices for the male character, one for the female, and the last for the rival.

But the values in the arrays contained variables that were not in that file, or the oak_speech.h file either.

I discovered that include/event_scripts.h defined the variables, but it did not have the values set. There was still a missing piece of the puzzle.

That missing piece was data/text/new_game_intro.inc.

I removed names from each of these places, added some new ones in and then built to see if it worked. And fortunately it did.

Debugging

There were some other tutorials that I wanted to follow, but I wanted to test before and after to ensure that the relevant change had been made. But I didn't want to have to play to get to a point where I was able to test whatever I had changed, and wondered how people had been managing to test their own projects.

Were they writing custom scripts that could be executed very early on? Or had they implemented some kind of debug menu? It turns out that adding a debug menu was one of the tutorials on the list, so I began to follow it.

"This is actually for pokeemerald," a disclaimer around the tutorial said, "but it will work for pokefirered too."

It did not.

FireRed does not have these methods and refuses to build.

HideMapNamePopUpWindow();
LoadMessageBoxAndBorderGfx();

It also has no idea what EnableBothScriptContexts is either, and it turns out that working implementations of the debug menu in Emerald don't even include that so I have no idea why it was there in the tutorial.

I added an include for new_menu_helpers.h, and found methods which seemed to be the FireRed equivalents of what the tutorial had said to use.

DismissMapNamePopUp();
LoadMessageBoxAndFrameGfx(0, TRUE);

From there I had a debug menu popping up in the game, although when closing it, it prevented some of the tiles from displaying and I was unable to move or open any other menus. I decided at this point that I was just going to copy-paste an entire debug file from Emerald and then fix up the build issues for FireRed.

There were definitions for flags that only existed in Emerald. Some were easily swapped out - towns in Hoenn could be replaced with towns in Kanto or the Sevii islands. Some unused flags in Emerald had been renamed, and they appeared to be unused in FireRed so I renamed them. I removed any references to the PokéNav and Battle Frontier.

And then I still had a bunch more errors that needed fixing, which mostly related to it not knowing about the functions it was trying to call.

One of my big frustrations with the homebrew / ROM scenes is there is little to no help if something goes wrong. Being a coder, I am used to finding solutions to problems, but the trail of breadcrumbs in these projects is a labyrinth that constantly leads to dead-ends with no answers. And those that do have answers are usually from unhelpful cunts that actually provide no real answer at all.

"It works on Emerald"

Well, I'm using FireRed so that's not really relevant, is it? And I'm willing to bet that if I cloned Emerald and pasted the code in that it also wouldn't work there because there is some other obscure thing I need to do that isn't documented anywhere.

I'd at least made some progress, even though there were still lots of build errors to solve. So I did what I do best and went for a nap. I will fix those some other day.

Popular posts from this blog

Phoning It In

The Month of Games #3 - Heart of the Cards