# Reverse-Engineering Game Boy Advance Games (and General Reverse-Engineering Advice) August 6, 2025 This is a follow-up to my previous post on some reverse-engineering I did for the Nintendo e-Reader.: 2025-08-06 And a more distant follow-up to my other page documenting the e- Reader.: https://nytpu.com/nintendo-e-reader/ As I wrote at the end of my previous post, I left a bunch of loose threads in my reverse-engineering because I just didn't feel like continuing unless I have something specific to research lol. However, if I'm leaving some leads as an exercise for the reader, I figured I should write some tips for someone new to reverse engineering---not that I'm skilled at all, I just know the very basics. This post is going to be focusing somewhat on the GBA and using it for all the examples just because that's where I'm most comfortable and like spending my time,[2] but the bulk of the tips should be applicable to reversing any embedded program. To start, while I'd like to say that "anyone can do it!", in realistic terms you really do need prior knowledge. Trying to follow a decompilation or disassembly of code that was likely janky even in its original source code isn't made any easier by not knowing how graphics work on the target system. In general, I'd say you should understand *the basics* of how to work with the target. You don't need to know every detail, but enough to make a homebrew program that displays basic graphics and can read user input, etc. At least have some resources at hand for looking up memory-mapped I/O registers and memory regions dedicated to specific tasks. You do also need pretty good working knowledge of the assembly for the main CPU architecture(s) of the target. At least enough to know the basic opcodes and the ability to look up any unfamiliar ones in documentation. I guess you could try to muddle through with just the decompilation, but reading the raw disassembly is usually just easier to read of clarifying confusing decompilations. Finally, you just have to be able to "figure out" how to do things with complex software like Ghidra or IDA. Ghidra isn't actually that confusing, but it has a lot of features so you have to be able to guess where you need to look and how actions are named. [1]: http://rampantgames.com/blog/?p=7745 [2]: Despite having never actually finished a game for it, I've spent many years just fucking around with black-triangle-like[1] tech demos; so I'd like to say I have an extremely in-depth knowledge of its hardware and subtleties. *** Okay, to start, I use Ghidra[3] just because it's free and really featureful and great; and a good hex editor like Okteta[4] for quickly inspecting and jumping around binary files is useful too. Luckily for me, GBA ROMs are really easy to look at because almost none of them used techniques like bank switching[5][6] like most prior consoles did, and it's all just one flat address space of code and data instead of having to separate out the code and graphics ROMs like e.g. the NES had. Unfortunately I don't have any tips for dealing with banked ROMs, nor for consoles where the ROM format used by dumpers and emulators has metadata rather than just being a raw dump of the ROM bytes. So, after importing a ROM into Ghidra and setting the correct architecture, the most helpful tip is to properly set up the entire memory map. Open up the ROM in CodeBrowser (the dragon icon), and click the little RAM stick icon on the right of the top icon bar. The GBA's memory map entered into Ghidra: files/e-reader/gba-memory-map.png Naturally, the memory map shown here is GBA-specific, but same gist for other platforms. Here is probably where you'd tell it about bank switching too? Obviously the ROM must be in the correct place or else the disassembly will be completely nonsensical, but the rest being marked as volatile and without a byte source is useful to tell it that it's an uninitalized RAM address rather than a ROM, and the RWX bits being set helps it know what analysis steps to do and how to guess what code is doing when accessing an address.[8] Now here's a big tip that, according to a handful of discussions I've had, people much more experienced than me apparently haven't thought of: rather than trying to follow everything using exclusively the disassembly/decompilation, I like to use an emulator with a debugger so I can step through the code while it's executing and identify areas of interest. If it's something early- on you can just breakpoint the ROM entry point and step from there, or you can set watchpoints for key MMIO registers you think might be involved, or you can just randomly pause at VBlank and manually step when you've played the game up to a point you're interested in. Then after you find the routine of interest, you can jump to the address in Ghidra and probably have a good enough understanding to label the function and some relevant data locations as a great starting point for exploring. With the GBA e-Reader in particular, this technique has an even easier shortcut. Just write a simple test ROM that calls the API function in question, set a breakpoint for `main`, and then once your main calls into the e-Reader ROM you know the specific entry point for that call and can then proceed to follow the code in Ghidra. (In the e-Reader there's a lot of indirection; but if you make a few API calls you can identify the general API setup and teardown routine used everywhere vs the actual underlying API routine.) And now for some basic Ghidra tips of the features I've personally found most useful: In the right-click menu you can add labels to arbitrary addresses, and when right-clicking on a function header you can rename the function from its autogenerated name. In both cases it'll automatically use that label as the name any time the rest of the code references that address. On the topic of references, the XREF column on the right of the disassembly lists all the places it's recognized as referencing that address. Very useful for seeing callers of a function or functions that touch a global variable, actually fundamental really. Another useful feature is also the "Create function" option. Ghidra sometimes struggles to tell if something is actually a function or just complex control flow, particularly for cases like the e-Reader where there's a bunch of functions exposed externally but never called within the ROM itself. Creating a function at a place you know gets called as one will trigger a reanalysis with the added knowledge that it is a function entry point, often making that snippet a lot more comprehensible. Finally, you can change the data type of bytes in a selected region. Useful if you know something that was detected as data is code, or know what it treats as individual bytes is actually an array of ints, or whatever. Here's where you have to apply your crazy human pattern recognition of what things likely are rather than solely relying on the computer to do all the work for you. [3]: https://www.nsa.gov/ghidra [4]: https://apps.kde.org/okteta/ [5]: https://en.wikipedia.org/wiki/Bank_switching [6]: as in banking the game code, IIRC a decent number had bank switching for the SRAM save data [7]: https://mgba.io/2014/12/28/classic-nes/#trick-2-code-in-vram [8]: Note that I marked the palette RAM, VRAM, and OAM as not being executable even though they technically are, so you might have to change that very rarely. My own personal games/tech demos very often execute code from VRAM for fun and expediency, but other than my games it's basically unheard of other than as a weird anti- emulation measure in one series of games[7]. In general, having them marked as non-executable is more convenient just to let Ghidra know that it's almost certainly data being written there. *** I'm sorry this post isn't like, a step-by-step guide, but the thing is that other than broad strokes like this, reverse-engineering is pretty specific to the program at hand and the platform that program is targeting. And you need enough prior knowledge that if one has that, I assume one could figure out the bulk of it on their own other than the initial leap in getting started. Maybe I should write a general GBA dev tutorial to supplement the wonderful Tonc[9] someday, although not like I'm particularly qualified since I've never made a real game lol. [9]: https://www.coranac.com/tonc/text/toc.htm * * * Contact via email: alex [at] nytpu.com or through anywhere else I'm at: gopher://nytpu.com/0/about Copyright (c) 2025 nytpu - CC BY-SA 4.0