All of the functions relating to
sprites, including those of the Object Attribute Memory (OAM) can be
found in C:\devkitPro\libnds\include\nds\arm9\sprite.h
Sprites are primarily all about the Object Attribute Memory (OAM)
functions: of which there are many necessary to complete, before you
can achieve the desired results. We start with oamInit():
void oamInit(OamState*
oam, SpriteMapping mapping, bool
extPalette);
OamState can only be either &oamMain or &oamSub depending on
which screen you are rendering the sprite to. This is a small (1kb)
data bank with direct 32bit access to the ARM 9 processor. In every
instance of it's usage it is entered into the parameters of a
function as a pointer, since it is updated by each function.
SpriteMapping
is an enumerator with one of 9 possible options. I always enter
SpriteMapping_1D_128
since I don't really understand any of the explanations: “1D tile
mapping 128 byte boundary between offset”...Yeah.
Extended palettes are only for 8bpp sprites.
(Very) typical example:
oamInit(&oamMain,
SpriteMapping_1D_128, false);
Much less standardized, and with a very
important return output, is the function oamAllocateGfx():
u16*
oamAllocateGfx(OamState *oam, SpriteSize
size, SpriteColorFormat colorFormat);
OamState, is the same as in the
previous function.
SpriteSize is an enumerator which
goes up to 64x64 pixel sprites (though, as with the maps, later, it
is possible to combine several sprites together to make something
larger, if necessary)
SpriteColorFormat is typically 256
colors, but can use, both, 16 color format and 16bit bitmaps.
The function returns a half-word
pointer. This is crucial. It describes the address in VRAM of the
allocated and bound sprite and should therefore be assigned to a
pointer variable for easy recall in later functions:
sprite->sprite_gfx_mem =
oamAllocateGfx(&oamMain,
SpriteSize_64x64, SpriteColorFormat_256Color);
If you are using the (GRIT) GBA Raster
Image Transmogrifier (which you should be), importing your image as a
.h file at the top of your code will result in your importing, both,
tile and palette data, of the form: filenameTiles and
filenamePal.
Your palette, you merely need to bind
directly to the SPRITE_PALETTE using dmaCopy, e.g.:
dmaCopy(manPal, SPRITE_PALETTE, 512)
dmaCopy is explained in further
detail, below, but is basically in the form of dmaCopy(from, to,
size-in-bytes)
the size, in this instance, is 512
since each color is a half-word or 2 bytes (16bit colours of the
form aBBBBBGGGGGRRRRR – alpha, blue, green, red – each 0 to 32)
and there are a maximum of 256 colours in any one palette.
It should be noted that it is
perfectly possible to, otherwise, save the address of the start of
the imported palette to a pointer variable, copy the address of this
pointer to the SPRITE_PALETTE using dmaCopy(), and therefore, switch
between several palettes by setting that variable to point at
different sets when needed.
Your tiles, alternatively, you need
to have a pointer variable reference their address, e.g.:
u8*
frame_gfx = (u8*) manTiles;
such that you can bring in the tiles as
an array and merely add the required amount of bytes to the end of
the address in order to advance it to the next frame of animation:
u8*
offset = sprite->frame_gfx + frame * 64*64;
then, it is entered into dmaCopy():
dmaCopy(offset,
sprite->sprite_gfx_mem, 64*64);
Remember that sprite_gfx_mem
variable? Yeah, this is the pointer variable which references the
address of the allocated and bound sprite, and that is why it was so
important to receive it from oamAllocateGfx().
There are a couple more OAM functions
which contain information about the sprite – usually relating to
special functionality, such as scaling and rotating – but which
otherwise have to be completed each time, even if you do not use such
aspects. These are:
void
oamSet(OamState* oam, int
id, int x, int
y, int priority, int
palette_alpha, SpriteSize size, SpriteColorFormat format, const
void* gfxOffset, int
affineIndex, bool sizeDouble, bool
hide, bool hflip, bool
vflip, bool mosaic);
Yep, that's a big one. This is pretty
much all of your attributes.
Id is the number of this set,
increasing from 0 to 127, for each new sprite.
x and y are positions on the
screen, for animation purposes.
Priority is between 0 and 3. Never
used it: always 0.
palette alpha is used in extended
Palette mode and with bitmaps. Set to 0.
SpriteSize and ColorFormat are the
same as used previously in oamAllocateGfx.
*gfxOffset is our favourite
pointer again – the pointer variable which references the address
of the allocated and bound sprite.
AffineIndex is used for
transformations between 0 and 32. Set to -1.
finally we end with five bool
transformations, which are fairly obvious from the names, and are
typically all set to false, (except for hflip – which is very
useful for turning your character around) thus:
oamSet(&oamMain, 0,
sprite.x, sprite.y, 0, 0,
SpriteSize_64x64, SpriteColorFormat_256Color,
sprite->sprite_gfx_mem, -1, false,
false,
manFlip, false,
false);
Finally, we have oamUpdate():
void
oamUpdate(OamState* oam);
A nice easy one to end with.