This documentation is a collection of relevant knowledge and gives you a overall thinking.
It may be on a steep learning curve and you will benifit from that. I have not much to teach you in fact. No tool mentioned here is made for hacking specially:
- They are developed and mantained by professional organizations.
- They have been used widely and well-documented.
Therefore you needn’t worry about that it is a toy made by a hacker for fun and its maintainer will disappear from Internet someday. Besides you are able to get support and help beyond a hacking community. Now that they already have many documentations and I am not a native English speaker, I won’t provide a step-by-step guide here. In fact I don’t memorize that either. Instead I will google it when I am in need.
You needn’t learn all of the tools I list here to start. I did have tried them all though, because I believe more choice => more freedom => more welfare. In addition, you may already have your favourite companion before reading this. It is meaningless to start a boring debate on something like which one is the best and blabla. However you are encouraged to share valuable infomation such as a better method to do something and other alternative methods, which can bring me more useful knowledge.
The organization of this documentation is the workflow:
- How to get the original C code? Reverse Engineer.
- How to modify or expand the C code? GBA Programming in C.
- How to merge C code into the game? Building.
- What if it doesn’t work as expected? Debugging.
De facto standard in reverse engineering.
Free version doesn’t support ARM architecture and its license is for enterprise and very expensive. Piracy may be more realistic.
- IDA Book: Strongly Recommended. I borrowed it from library and read it completely.
- IDA Pro newbie Tutorial (GBA, SNES, loader script, GDB debugger)
- IDA Pro Tutorial in pokecommunity
- IDA GBA loader
- My GitHub
- Lan’s GitHub
Totally free and open source. It has a GUI called Cutter.
- Radare2 Book
- Reverse engineering a Gameboy ROM with radare2
- Radare2 has a native support to load GBA ROM
- Use free online service to assist the routine analysis
It supports file type “ningba”.
Totally free and open source. GUI.
Totally free and open source. GUI.
Hopper, Binary Ninja, Relyze and so on.
I only play with some of them a little and they are poor / not work / not free / few user so I don’t have much to share with you. Try them by yourself.
In fact, you need to learn this part before the previous part.
Most GBA games including Fire Emblem are developed using C. C is a powerful language which enables you to access hardware directly and also a popular language in embedded development. It is easier to connect assembly with C than other high level programming languages. Of course assembly is more efficient but it is more difficult to read and write. In addition, assembly is highly specific to CPU / platform and I don’t only hack GBA games.
I learnt C in college and from a standard textbook, though it is controversial on the Internet. There are plenty of free course resources on the Internet.
Don’t learn C from any GBA hacking tutorial. Be sure to learn pointer well, because it will be a bridge between you and GBA hardware.
- C Tutorial
- C Tutorial
- C Tutorial
- Learn C Programming
- Embedded Systems/C Programming
- C programming for embedded microcontroller systems
GBA is an old and outdated game console, so it also has plenty of resources and documentations on the Internet.
- tonc: Strongly Recommended. I have already read it completely.
- gbatek: Strongly Recommended. I have read it many times.
- AGB Programming Manual: Official documentation from Nintendo. It has more graphs and charts.
- GBA Dev: “Here we are, 16 years later, doing the same thing.”
C source code (.c) is a pure text file, but you want it to run in the game. That is what this part for.
All you need to do the job is a cross-compilation toolchain. It allows you to build a binary running on GBA (ARM architecture CPU) on your PC(x86 architecture CPU). That is the meaning of “cross”. Therefore, you cannot build it using the same compiler as the one you use when learning C programming in the previous part.
Totally free, open source and used widely, so it has many variants which built with different configurations and patches. Followings are what we can use here:
- devkitpro: de facto standard in homebrew. You only need to install devkirARM, one of its components.
- GNU Arm Embedded Toolchain: more frequent update and easier to install (apt-get).
- agbcc: for decomp project. It is based on the source code of gcc included in the disk which Nintendo sent to developers. It is an old version of gcc for binary matching.
- Of course you can also build one by yourself because it is open source. However, it is not an easy job as you expect. A tool like crosstool-NG is helpful.
It is ARM official commercial product so a license is needed. It has a higher efficiency than free gcc. It is included in SDT / ADS / RVDS (RVCT Compiler) / MDK-ARM / DS-5. If you are an embedded engineer, you may be familiar with one of them.
You are free to replace gcc with Clang if you like.
In fact, ARM Compiler 6 is based on LLVM and Clang technology.
It is convenient for research purpose.
It is not a must, but it is convenient. It doesn’t matter which you select, and most programmers already have their favorite one. Besides a text editor extensive to an IDE is also included in this part, though it is not a real IDE strictly speaking. There are too many choices here, I only introduce those I have tried.
Visual Studio Community edition is free.
Eclipse is an open source project, so it also has many variants / plugins.
- Eclipse CDT: Guide It supports C/C++ programming in Eclipse. Free.
- Arm DS-5: Guide ARM official IDE. Its community edition is free, though ARM compiler is not available, but it allows you to select gcc.
- GNU MCU Eclipse: for ARM & RISC-V development. Free.
It is not free. I show it in this video. I use it because my senior recommended it to me and taught me to use it. It is good for C programming.
Install plugins: windows-arm-none-eabi, ARM, C/C++, C/C++ Clang Command Adapter, C++ Intellisense and so on. Dig a mine in its plugin store.
It supposts json scripts.
Install plugins: HEX-Editor, NppExec, Task List, NppGTags,TagsJump, TagsView and son on. Dig a mine in its plugin manager.
It supports many custom language syntax highlight:
- comes with old devkitpro
- recommended in tonc
- some homebrew tutorials also use that
- removed in latest devkitpro as an obsolete package.
- If you find a .pnproj file in the project’s folder, you can open it with this one.
It makes it easier to jump between source files.
It makes it easier to build the project.
- Overview of Build Systems
- List of build automation software
- We use GNU Make here
- A template makefile is included in devkitpro
- Makefile can be generated automatically by tools like cmake, omake, automake and so on
- Make also have other implementations such as nmake in Visual Studio
- There also exist other build systems such as Meson and Ninja
Followings are guides to build NDS project with CMake and SCons:
The big difference between homebrew and hacking is whether you have the complete source code. How to build the project without original game source code? This is a key point, so I will explain it in detail.
When you learn C programming, your first program may be “hello world”. It is a simple program, there is only one line of core code: “printf(“Hello World\n”);”. However, what is “printf”? How does it display “Hello World” on your screen? You never write any code for it. It is from a library. A static library usually has a “.a” extension on Linux. It consists of many object files. It is a pre-built binary so you cannot read its source code. However, it works in your program, because a linker links your code to the library.
Notice that I name this part as “Building” instead of “Compiling”. In fact, it has 2 steps: Compiling and Linking.
- Compiling: A compiler compiles your source files to object files.
- Linking: A linker links all object files to a .elf file.
It doesn’t matter where the object files come from. It may be compiled from your source files; it may be included in a library; it may be provided by others.
Therefore, it doesn’t matter that you do not have the original game source code, because the linker doesn’t care that at all. A compiler reads source code, but a linker doesn’t.
In fact, Nintendo also provides developers with object files rather than source code to keep trade secrets and protect copyrights. You can link your code with it, but you cannot read its source code.
To conclude, create an object file for the whole game and link it with your compiled code. That’s all.
This is an example shows how to do that. Assemble it and you will get the object file.
When you modify the source code of a function, you had better to make a wrapper function for it, unless you ensure the size of compiled code is not larger than the original one, otherwise it will destroy the next function. Allocate a specific section for the wrapper function so that we can control its address when linking via a linker script or a scatter file. Surround the core function with “#pragma long_calls” and “#pragma long_calls_off”.
If you don’t understand it, here is an example. You can follow it as a rule.
This is a template linker script. You can install and uninstall your hack in it. It supports C comments.
The linker will report a section overlap error when linking, but you can use command option to disable it and link it successfully. It will produce an ELF format file (a.out by default) at last. You can use objcopy to dump binary game ROM from it. This “a.out” is necessary for the next part. If you follow this tutorial and use EA instead of a linker, you will be unable to debug your C code.
If your code doesn’t run as expected in the game, you will need to debug it to fix the problem.
It allows you to focus on your code itdelf instead of assembly language. A debugger loads debug infomation from the ELF generated from the previous part.
You debug on your pc but your code runs on GBA, so you need to do remote debugging. An emulator starts a gdb server and a source level debugger connects to it via TCP port.
Compiler option for debugging: -O0 -g. Difference between a Debug and Release build.
- Start gdb server on an emulator
- mGBA Recommended
- Some old tutorials use that because the gdb server stub of old VBA doesn’t work.
- Use gdb in the cross toolchain, of course.
TUI is not supported in the Windows version. Solutions for Windows users:
- Build it from source. The TUI is available only when GDB is configured with the --enable-tui configure option
- Run Linux binary with wsl.
Python extension is not supported in the devkitpro version. Solutions:
- Build it from source. This feature is available only if GDB was configured using --with-python.
- Use arm-none-eabi-gdb-py in GNU Arm Embedded Toolchain.
- TUI is not supported in the Windows version. Solutions for Windows users:
GDB Front Ends
- It is not a must. Only for convenience.
- Insight is removed in latest devkitpro as an obsolete package. You can get it here.
- Add LLDB support to gdb remote debugging stub
- The feature is added after the latest release, so you need to build VBA-M from source. Here is my built binary.
- mGBA’s support to LLDB
- Visual Studio
- Eclipse CDT
- ARM DS-5
- GNU MCU Eclipse
- Visual Studio Code
- Advance Debugger
- GDB is terminal, so it is not difficult to integrate. Google it.