arraysincludestatic-linkingprecompile

Populating an array with include directives


This morning I learned that the famous videogame Super Mario 64 has been fully decompiled back to C source code. Just out of curiosity, I've decided to look through it, and I noticed something that I had never seen before.

// 0x09000000
ALIGNED8 const u8 machine_09000000[] = {
#include "textures/machine/ttc_textures.00000.rgba16.inc.c"
};

It looks like they put an include directive inside of an array. This is done repeatedly throughout the whole program.
I've been studying C for a little while now, and I consider myself reasonably fluent with this language, but this is something extremely novel to me and I've got so many questions about it.

1) Is it actually legal or even recommended to do something like this?
2) Why would you do this?
3) Why is the include referring to a *.c file?
4) Why is the type set to u8 (which should be a standard alias for unsigned char, if I've got that straight)?
5) What's that ALIGNED8 macro? Is it something standard?

I've tried to gather information on my own, but wasn't able to find much on this topic. If you want to look at the source code yourself, here's the link: https://github.com/n64decomp/sm64


Solution

  • From a fellow a bit brighter than myself-

    1 & 2: we're including an image converted into C. There are other techniques for this than arrays within .c code, but that's the technique the sm64 devs used, so we mimic it. And instead of copy-pasting C array we have the build system generate (parts of) C from images automatically, which then #included. It works decently well, best we could do under the circumstances. (Assuming we want to keep everything in C instead of assembly -- in assembly we'd .incbin which would be cleaner, but it becomes less portable.)

    3: .h would be wrong, since it's not a header file that declares functions, types, etc., but rather data (a partial C file)

    1. it's u8 because the file we're including is just a binary blob of data, and we don't want to make endianness assumptions

    2. ALIGNED8 is actually ignored on IDO. Its effect is to 8-byte-align the array on GCC. The reason is that addresses sent to the RSP have to be 8-byte-aligned, and that's not guaranteed without such a directive. In particular, GCC happily reorders variables in ways that make them non-8-byte-aligned. IDO doesn't do that sort of reordering (it just emits arrays in source order), but the variables just happen to end up 8-byte-aligned there anyway. it helps to know what #include does, which is just include the text of another file from that definition it follows that yes, it's absolutely legal to use it in that context; whether it's wise is another question.