GBA Hacking in C

[TOC]

Perface

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.

Reverse Engineer

IDA Pro + HexRays



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.

GBA Loader

Radare2 + RetDec/Radeco



Totally free and open source. It has a GUI called Cutter.

It supports file type “ningba”.

Ghidra



Totally free and open source. GUI.
GitHub

GBA Loader

REDasm

Totally free and open source. GUI.



Github

GBA Loader

Others

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.
IDA rivals
C decompiler

GBA Programming in C

In fact, you need to learn this part before the previous part.

C Programming

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.

GBA Programming

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.”

Building

C source code (.c) is a pure text file, but you want it to run in the game. That is what this part for.

Toolchain

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.

GNU Toolchain

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.

Online Manual

ARM Toolchain

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.

Online Manual

LLVM

You are free to replace gcc with Clang if you like.
In fact, ARM Compiler 6 is based on LLVM and Clang technology.

Online Manual

Online Compiler

Compiler Explorer
It is convenient for research purpose.

IDE

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

Visual Studio Community edition is free.
Guide

Eclipse

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.

Source Insight

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.

Visual Studio Code

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.

Notepad++

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:

Programmer’s Notepad

Others

VIM, Emacs, Atom and so on.
I use VIM when programming on a remote Linux server.

Tagging System

It makes it easier to jump between source files.

Build System

It makes it easier to build the project.

Followings are guides to build NDS project with CMake and SCons:

Hacking-specific Configuration

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.

  1. Compiling: A compiler compiles your source files to object files.
  2. 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.

Debugging

If your code doesn’t run as expected in the game, you will need to debug it to fix the problem.

Source Level Debugging

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.

GDB

  • Start gdb server on an emulator
    1. mGBA Recommended
    2. VBA-M
      • Fix remote gdb support
      • The bugfix is after the latest release, so you need to build VBA-M from source or use gdb version lower than 8.0. Here is my built binary.
    3. VBA-SDL-H
      • Some old tutorials use that because the gdb server stub of old VBA doesn’t work.
      • VBA-SDL-H2
  • Use gdb in the cross toolchain, of course.
  • Manual
    • TUI is not supported in the Windows version. Solutions for Windows users:
      1. Build it from source. The TUI is available only when GDB is configured with the --enable-tui configure option
      2. Run Linux binary with wsl.
    • Python extension is not supported in the devkitpro version. Solutions:
      1. Build it from source. This feature is available only if GDB was configured using --with-python.
      2. Use arm-none-eabi-gdb-py in GNU Arm Embedded Toolchain.
  • 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.

LLDB

Integrate to IDE

Assembly Level Debugging

  • NO$GBA Recommended
    Place the ELF file in the source folder and load it to NO$GBA. Read its help content.
  • IDA Debugger
    • Start GDB server on the emulator
    • Connect IDA Debugger to it
    • Tutorials
    • IDA Pro is mainly for static analysis, so I seldom use its debugger
18 Likes

well nice im using c language in my scholl programing class im the best in class

Nice to meet you here Tiki, it’s nice for you to share such a toturial and tools for IDA Reversing. For now I’m encountered with a problem with IDA that, how to rename the function? this is what I’v gotten:


actually I’ve found your artwork, Function Library, and I thought that may be a key to rename it?
hope for your help!

时隔两年再来重新学习这个帖子,确实感觉受益匪浅

1 Like