Introduction
In the palib homebrew community (Nintendo DS homebrew development) is #include “data.c” a daily occurence. Several people point out not to follow this approach, because it’s “bad practice”.
In this article, I’m not so much trying to convince you about the evilness of including data, but I’m telling you when this approach is appropriate, when it isn’t and why. The article assumes you use devkitARM to build your .nds files.
History
I guess the palib author adapted this approach from the early HAM days. HAM was around 2001-2005 a very popular free software development solution for the Nintendo Game Boy Advance, including almost everything you would need to create games for this lovely device.
The example projects in HAM used to integrate resources (graphics, sounds, etc…) by converting resources to C source code arrays. The generated files were #included in the example source file (main.c).
The intention behind this approach makes sense for the Game Boy Advance. GBA games are shipped on Game Pak’s that consist of Read-Only-Memory (ROM) containing the program code (.text) and data (.rodata). When you declare const data on the heap, the memory is allocated in ROM. In order to load graphics to video ram, you could tranfer image data directly from ROM to Vram, without the need to have it in main memory.
What’s the deal with that?
The Nintendo DS on the other hand does not feature this ROM section in the traditional way anymore, everything (code, data) is located in the 4MB main memory region. When you #include data in your program code, memory for it is always allocated and present in main memory, even when you don’t need it!
Let’s take a simple example to clearify: Imagine you create a platform game with several levels. Each level features a different set of graphics (sunny, snowy, rainy). If you would #include graphics in program code, memory for every single graphic would be allocated in main memory for every level in each level. So you would have graphics of level 1 (sunny) in main memory, even when you play level 2 (snowy). It might work for the first 1 1/2 graphic-sets, but then exceeds the main memory capacity of 4MB eventually.
As you already know, program code is located in main memory too, so you can’t even calculate with 4MB for resources. As far as my experience goes, real-world-projects use about 400-600 KB for program code, leaving you with only about 3.5MB for internal game management and resources.
#include or not #include, that’s the question
When you aim for a game with a decent quality, you can’t #include data as this would blow up memory, you have to load resources from the file system. To be more precise, you load only resources to memory, that you actually need in the particular level (file i/o handling in nds homebrew).
However, sometimes it’s necessary to have access to resources all the time, for example to display on-screen debug text. For such “low-level-system”, you want to have the resource in memory, because what happens when loading of the debug-font resource would fail?! You couldn’t even display an error at this time, because the font is missing! For this special case, I suggest you either convert the resource in question to an object file (.o) and link this one, or convert to assembler code and assemble as well as link, but don’t #include.
If you generate C code, rather than assembler, the C compiler must parse the code, then generate the corresponding assembler code, that is being transformed to object code afterwards. When you don’t like waiting for your compiler to complete, choose .o or .s as target!
Why did I just say “don’t #include”?
When you create a seperate source file that contains data and store it in your “source” directory, it’s being compiled only when the target object file (.o) is either missing or the source file is newer. As for the debug font resource, this would be once or at least very rarely. After the source file has been compiled and transformed to an object file, it only needs to get passed to the linker when you build the project. It removes the need to compile the file every time again.
When you #include data in a file where you currently work at, the compiler must parse the #included data every time you change something on the code and recompile. Performance-wise isn’t it really much of a problem anymore, since todays computers have several GB memory, multi-core processors and relatively fast hard-drives, but it makes the compile process slower anyway, which sums up when your project grows.
I think the error that occurs most often when dealing with #include data is multiple definitions of the same symbol. This occurs when you include a file in more than one source file, there are dozens of these posts on the palib forum!
How to embed data
You want to embed “debugfont.bmp” in your game, so it’s always in memory, how you doing that? It’s simple! Use your favorite graphics converter to ouput a “binary” version of the converted data, lets call it “output.bin”. In order to embed output.bin, all you have to do is to move it to the “build” directory of your project. The example makefiles of libnds/devkitARM include a target that takes every .bin file in the “build” directory and convert, compile and link it.
If you want to do it by hand, use devkitARM/bin/bin2s.exe to convert the .bin file to assembler code and move the output file to your “source” directory. Next time you build the project, the file gets compiled and linked.
Conclusion
- You can’t complete a game project by #include’ing data, which contains more than about 3.5MB resources.
- Sometimes you want to embed data, eg graphic for debug text, compile and link the file.
- #include data is error-prone, multiple definition of…
- #include data slows down compile process which can become significant as the project grows.

Add A Comment