FAQ.

Why did you make this?

After finishing the jam game “Goodboy Advance”, Rik and I decided to make a post-jam version, which eventually became Goodboy Galaxy. The old jam code sucked, so we planned to rewrite it from scratch. And C was slowing us down a lot - it’s verbose, lacks good abstraction mechanisms, and does a terrible job at protecting you from your own mistakes.

At that time I was also learning Nim to make desktop games with SDL - something it’s very good at. I wasn’t expecting Nim to work on the GBA. After all, many compiled languages such as Haxe and Swift have hefty runtimes making them unsuitable for embedded platforms. But I gave it a try and to my surprise it worked brilliantly!

I wrapped the entirety of libtonc to create a library called nim-tonc. As I grew comfortable with Nim, I learned how to write more idiomatic code instead of treating it as just a “nicer C”. I renamed the library to natu and started using my experience to create nicer APIs:

  • Before: REG_DISPCNT = (REG_DISPCNT and not DCNT_MODE_MASK) or DCNT_MODE4

  • After:   dispcnt.mode = 4

While working on the game, I tackled problems such as image conversion, palette management and sprite tile alloction. These eventually made their way into Natu for re-use in future projects.

Natu is for those who want to enjoy writing GBA games in a flexible compiled language that feels like a scripting language. You get to work directly with the hardware and build your own engine, but you don’t have to reinvent the entire wheel.


How does Natu compare to …

libtonc

libtonc is the accompanying library to the excellent Tonc tutorial. It exposes the entire GBA hardware in C, and provides several utilities such as fixed point math, text rendering, and interrupt management.

Natu started as a wrapper for libtonc, also wrapping additional libraries such as Maxmod and posprintf. New features were added, some libtonc modules were eventually replaced with idiomatic Nim code, and others by alternatives such as ugba’s interrupt manager. However many parts remain, notably Tonc Text Engine and the Surface API.

Butano

Butano is a high-level engine using modern C++ ideas such as RAII to save you the burden of managing resources (VRAM, palettes, etc.).

Natu is lower-level than Butano, encouraging you to read and write I/O registers directly. Like Butano, it provides an asset conversion system, and allocators for Obj VRAM and Obj Pal RAM. Unlike Butano, you have to call the allocators manually. Also there are no allocators for backgrounds, you just manage them by hand.

It’s worth noting that Nim’s ARC memory-management strategy allows you to implement the same RAII patterns as in C++, so you could use Natu to build a “Butano-lite” if you wanted. If you were to do this, you’d find the resulting code to be way shorter!


Nimble says “Package 'natu' has an incorrect structure”?

If you see a warning like this, don’t worry:

Warning: Package 'natu' has an incorrect structure. It should contain a single directory
hierarchy for source files, named 'natupkg', but file 'backgrounds.nim' is in a directory
named 'natu' instead. This will be an error in the future.

The structure is fine, Nimble is just overly prescriptive. The warning predates several additions to the language such as the ./ prefix for local imports, and the std/ prefix for stdlib imports. Hopefully they’ll remove it soon.


Error “<thing> is not in region .iwram

This likely means your global / top-level variables are occupying too much IWRAM, which is the small region of memory where all variables go by default (see Where do my code & data end up in memory?).

To fix this, you could try any of the following:

  • If you have some values that never changes, you could make them const.

  • If the variables aren’t performance-critical, use {.codegenDecl:DataInEwram.} to move them into EWRAM.

  • Look out for memory-hungry variables such as large arrays/objects, and try reducing their size by using smaller datatypes, using the {.bitsize.} pragma to pack your objects, and removing unnecesary fields.

  • Make your variables local to allocate them on the stack, or turn them into ref objects or manually-managed ptrs to allocate them on the heap. This ensures that they won’t consume memory when they’re not in use.


Where do my code & data end up in memory?

By default:

  • Procedures are compiled to Thumb code and placed in ROM.

  • Local variables are allocated on the stack, which is in IWRAM.

  • `ref` objects are allocated on the heap, which is in EWRAM.

  • Top-level variables are generally placed in IWRAM, but:

    • `let` variables go in ROM only if they’re ordinal types (or arrays of such) whose values are known at compile-time.

    • `const`s go in ROM, or may have their values substituted in-place at the point of usage (if they’re small).

The following modifiers are available for use with the codegenDecl pragma to control how code and data are placed.

  • ArmCodeInIwram - the procedure/function will be compiled to ARM code and placed in IWRAM. This can give a substantial speed boost!

  • ThumbCodeInEwram - the procedure/function will be compiled to Thumb code and placed in EWRAM. This may be occasionally useful for purposes such as a “cartridge removed!” screen, or for code which reads from SRAM.

  • DataInEwram - the top-level variable will be placed in EWRAM instead of IWRAM.


I made a game! How do I distribute it legally?

Yo, congrats! Natu is under the zlib license which means you don’t have to credit me (though it would be nice if you did!) however, many of its dependencies (libtonc, maxmod, etc.) are under the MIT or ISC licenses, which require that the author’s copyright notice and the full license text be included somewhere alongside your game.

The easiest way to follow this is simply to include a text file with your game, listing all the dependencies, their copyright notices, and their licenses. Here’s an example text file from a project made with Natu that you could use (adapting the text at the top to suit your project, and also adding any additional libraries that you may have used).

Another option would be to include the text in the game itself (on a ‘licenses’ screen or such). This takes some work but has the advantage that the license text can’t become separated from the game, so it’s impossible for anyone to distribute it incorrectly.