TONC consists of three components: a text section (the actual tutorial), an examples repo with all the source code & makefiles of the various demos, and a library called libtonc which holds all the useful/reusable code introduced throughout the tutorial.

Previously these were all distributed as zip files, but times have changed and now they exist in separate git repositories. They will now be explained in more detail:

Tonc text

The text section, which you’re reading now, covers the principles of GBA programming in detail. The focus here is not so much on how to get something done, but how things actually work, and why it’s done the way it’s done. After that the how often comes naturally. Every chapter has one of more demonstrations of the covered theory, and a brief discussion of the demo itself.

Please, do not make the mistake of only reading the demo discussion: to properly understand how things work you need to read the text in full. While there are optional parts, and whole pages of boring text that seem to have little to do with actual GBA coding, they are there for a reason, usually there’s extra conceptual information or gotchas.

At first, the text part had only very little code in it, because I figured the demo code would be at hand and flicking between them would not be annoying. Well, I’ve realized that I figured wrong and am in the process of including more of the code into these pages; maybe not quite enough to copy-paste and get a clean compile, but enough to go with the explanations of the demos.

The main language will be C, and a smidgeon of assembly. These are the two main languages used in GBA programming even though there are others around. Since the basics of programming are independent of language, it should be possible to adapt them for your chosen language easily.

GBA programming is done close to the hardware, so I hope you know your pointers, hexadecimal numbers and boolean algebra/bit-operations. There’s also a fair amount of math here, mostly vector and matrix stuff so I hope your linear algebra is up to speed. Lastly, I am assuming your intellectual capacities exceed those of a random lab monkey, so I won’t elaborate on what I consider trivial matters too much.

Aside from the introduction and appendices, the text is divided into 3 parts. First there’s ‘basics’, which explains the absolute essentials for getting anything done. This includes setting up the development environment, basic use of graphics and buttons. It also contains text on what it means to do low level programming and programming efficiently; items that in my view you’d better learn sooner rather than later. The second part covers most of the other items of the GBA like special graphic effects, timers and interrupts. The final section covers more advanced items that uses elements from all chapters. This includes writing text (yes, that’s an advanced topic on the GBA), mode 7 graphics and a chapter on ARM assembly.

The Markdown source for the text is all available on GitHub, so please feel free to contribute if you find a typo or something that can be improved.

Tonc code (libtonc & examples)

The source code to all the demos mentioned in the text can be found in the libtonc-examples repository. Like the text, the examples themselves are divided into 3 parts: basic, extended and advanced. There is also a lab directory with a few interesting projects, but which might not be quite ready. Still interesting to look at, though.

The language we’ll be using is C with a dash of assembly (but not C++). I am working under the assumption that you are familiar with this language. If not, go learn it first because I’m not going to show you; this is not a C course. I do have some links to C tutorials in the references.

Unlike some older GBA tutorials, tonc uses makefiles instead of batch scripts to build the example projects, because they’re just Plain Better™. How to use these will be explained in the next chapter, but if you just wanted to check out the pre-compiled example ROMs, those are still available here:

The examples depend on libtonc, a library containing all the important #defines and functions introduced throughout the tutorial. This also includes text writers for all video modes, BIOS routines, a pretty advanced interrupt dispatcher, safe and fast memory copy and fill routines and much more. Historically libtonc was included alongside the examples, but nowadays it comes with devkitARM, so you don’t have to download it yourself.

Statement of Purpose

I wrote Tonc for two reasons. Firstly, as a way to organize my own thoughts. You often see things in a different light when you write things down and learn from that experience. Secondly, there is a lot of very bad information in other tutorials out there (the only exceptions I know of are the new PERN and Deku’s sound tutorial. Yes, I am aware of how that sounds, but unfortunately it happens to be true. A number of examples:

  • Only very basic information given, sometimes even incorrect info.
  • Strong focus on bitmap modes, which are hardly ever used for serious GBA programming.
  • Bad programming habits. Adding code/data to projects by #including the files, Using ancient toolchains, non-optimal compiler settings and data-types, and inefficient (sometimes very inefficient) code.

If you are new and have followed the other tutorials, everything will seem to work fine, so what’s the problem? Well, that’s part of the problem actually. Everything will seem fine, until you start bigger projects, at which time you’ll find hidden errors and that slow code really bogs things down and you’ll have unlearn all the bad habits you picked up and redo everything from the start. The GBA is one of the few platforms where efficient coding still means something, and sometimes all it takes is a change of datatype or compiler switch. These things are better done right from the start.

I’ve tried to go for completeness first, simplicity second. As a certain wild-haired scientist once said: “Make things as simple as possible, but no simpler.” This means things can seem a little technical at times, but that’s only because things are pretty technical at times, and there’s no sense in pretending they’re not.

In short, Tonc is not “GBA Programming for Dummies”, never was, never will be. There’s far too much of stuff for Dummies already anyway. If you consider yourself a dummy (and I do mean dummy, not newbie), maybe Tonc isn’t the right place. If you’re serious about learning GBA programming, however, accept no substitute.

Terminology and Notation

I’m a physicist by training which means that I know my math and its notational conventions. I use both quite often in Tonc, as well as a number of html-tag conventions. To make sure we’re all on the same page here’s a list:

Type notation example
bit n in a foo foo{n} REG_DISPCNT{4} (active page bit)
code <code> tag sx
command/file <tt> tag vid.h
matrix bold, uppercase P
memory hex + code 0400:002eh
new term bold, italic charblock
variable italics x
vector bold, lowercase v

I also use some non-ASCII symbols that may not show up properly depending on how old your browser is. These are:

α, β, γ Greek letters
½ one half
¼ one quarter
¾ three quarters
greater or equal
double-sided arrow
is in (an interval)
⟨ ⟩ ‘bra’ & ‘ket’
right arrow
² superscript 2
× times

I also make liberal use of shorthand for primitive C types like char and int and such. These are typedefs that better indicate the size of the variable that’s used. Since this is very important in console programming, they’re quite common. Anyway, here’s a list.

base type alt name unsigned signed volatile
char byte u8 s8 vu8 / vs8
short halfword u16 s16 vu16 / vs16
int word u32 s32 vu32 / vs32

Finally, there are a number of different notations for hex that I will switch between, depending on the situation. The C notation (‘0x’ prefix, 0x0400) is common for normal numbers, but I’ll also use the assembly affix at times (‘h’, 0400:0000h). The colon here is merely for ease of reading. It’s hard to tell the number of zeros without it.

Register names and descriptions

Getting the GBA to do things often involves the use of the so-called IO registers. Certain bits at certain addresses of memory can be used as switches for the various effects that the GBA is capable of. Each register is aliased as a normal variable, and you need to set/clear bits using bit operations. We’ll get to where these registers are and what bit does what later; right now I want to show you how I will present these, and refer to them in the text.

Each register (or register-like address) is mapped to a dereferenced pointer, usually 16bits long. For example, the display status register is

#define  REG_DISPSTAT *(u16*)0x04000004     

Every time I introduce a register I will give an overview of the bits like this:

REG_DISPSTAT @ 0400:0004h
F E D C B A 9 8 7 6543210
VcT - VcI HbI VbI VcS HbS VbS

The table lists the register’s name (REG_DISPSTAT, its address (0400:0000h) and the individual bits or bitfields. Sometimes, bits or entire registers are read- or write-only. Read-only is indicated with a red overbar (as used here). Write-only uses a blue underbar. After it will be a list that describes the various bits, and also gives the #define or #defines I use for that bit:

0 VbS DSTAT_IN_VBL VBlank status, read only. Will be set inside VBlank, clear in VDraw.
other fields
8-F VcT DSTAT_VCT# VCount trigger value. If the current scanline is at this value, bit 2 is set and an interrupt is fired if requested.

The full list of REG_DISPSTAT can be found here. The #defines are usually specific to tonc, by the way. Each site and API has its own terminology here. This is possible because it’s not the names that are important, but the numbers they stand for. That goes for the names of the registers themselves too, of course. One last point on the #defines: some of the ones listed have a hash (‘#’) affix. This is a shorthand notation to indicate that that field has foo_SHIFT and foo_MASK #defines, and a foo() macro. For example, the display register has an 8-bit trigger VCount field, which has ‘DSTAT_VCT#’ listed in the define column. This means that the following three things exist in the tonc headers:

#define DSTAT_VCT_MASK      0xFF00
#define DSTAT_VCT_SHIFT          8
#define DSTAT_VCT(_n)       ((_n)<<DSTAT_VCT_SHIFT)

Lastly, as shorthand for a specific bit in a register, I will use accolades. The number will be a hexadecimal number. For example, REG_DISPCNT{0} is the VBlank status bit (VbS above), and REG_DISPCNT{8-F} would be the whole byte for the VCount trigger.

On errors, suggestions

As much as we (cearn and the community) have tried to weed out things like spelling/grammar errors and broken links, it’s surely possible some have slipped by. If you find some, please raise an issue (or even better, make a pull request) on the GitHub repo. Of course, if things are unclear or *gasp* incorrect, or if you have suggestions, we’d like to know that as well! You can also reach us on Discord / IRC or the Forums.

And, of course:

This distribution is provided as is, without warranty of any kind. I cannot be held liable for any damage arising out of the use or inability to use this distribution. Code has been tested on emulator and real hardware as well as I could, but I can’t guarantee 100% correctness. Both text and code may be modified at any time. Check in once in a while to see if anything’s changed. There is also a log in the appendices.

OK that’s it. Have fun.

Jasper Vijn (jakvijn at gmail dot com) and the community