Importing assets

Importing your graphic and audio files into a GBA game can be annoying, but with Butano and this guide you will be good to go.

GBA ROMs by themselves don't include a file system, so you can't put a couple of *.bmp files into a folder and expect to read them directly from the GBA side.

This means that all the game's data has to be added directly to the binary. Don't worry, because Butano build system does this for you. When you drop a file into an assets folder, Butano:

  • Generates a GBA-friendly version of it.
  • Inserts it into the ROM.
  • Creates a C++ header into the build folder containing the required information to use the assets with ease.

Let's see how to import image and audio files.

Images

By default image files go into the graphics folder of your project.

Butano for now is a little finicky about the images it likes, sorry.

The required image format is the following:

  • BMP without compression nor color space information.
  • 16 or 256 colors only.
  • The first color in the color palette is the transparent one, so in most cases it will not be shown on screen.

If you are using GIMP for your images, remember to disable color space information:

Image

However, the recommended tool to ensure that your images are compatible with Butano is Usenti:

Image

Usenti is a simple bitmap editor for paletted images, it is like the good old Paint but with various palette/color manipulation tools.

If you are not going to use Usenti for your images, at least remember to check them with it when they are not displayed as expected.

A single *.bmp file is not enough to display graphics on the GBA. You must accompany it with a *.json file with the same name specifying if it is a sprite or a background and some more info.

Let's see how to do it.

Sprites

An image file can contain multiple sprite images. If it only contains one sprite image, its size must be one of the specified by bn::sprite_shape_size.

Multiple sprite images are allowed by layering them down on the vertical axis:

Image

An example of the *.json files required for sprites is the following:

{
    "type": "sprite",
    "height": 64
}

The fields for sprites are the following:

  • "type": must be "sprite" for sprites.
  • "height": height of each sprite image in pixels. For example, if the specified height is 32, an image with 128 pixels of height contains 4 sprite images.
  • "tiles_compression": optional field which specifies the compression of the tiles data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "palette_compression": optional field which specifies the compression of the colors data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "compression": optional field which specifies the compression of the tiles and the colors data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.

If the conversion process has finished successfully, a bn::sprite_item should have been generated in the build folder.

For example, from two files named image.bmp and image.json, a header file named bn_sprite_items_image.h is generated in the build folder.

You can use this header to create a sprite with only one line of C++ code:

#include "bn_sprite_items_image.h"

bn::sprite_ptr sprite = bn::sprite_items::image.create_sprite(0, 0);

Sprite tiles

An image file can contain multiple sprite tiles sets. If it only contains one sprite tiles set, the size of the image must be one of the specified by bn::sprite_shape_size.

Multiple sprite tiles sets are allowed by layering them down on the vertical axis:

Image

An example of the *.json files required for sprite tiles is the following:

{
    "type": "sprite_tiles",
    "height": 64
}

The fields for sprite tiles are the following:

  • "type": must be "sprite_tiles" for sprite tiles.
  • "height": height of each sprite tiles set in pixels. For example, if the specified height is 32, an image with 128 pixels of height contains 4 sprite tiles sets.
  • "compression": optional field which specifies the compression of the tiles data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.

If the conversion process has finished successfully, a bn::sprite_tiles_item should have been generated in the build folder.

For example, from two files named image.bmp and image.json, a header file named bn_sprite_tiles_items_image.h is generated in the build folder.

You can use this header to create sprite tiles with only one line of C++ code:

#include "bn_sprite_tiles_items_image.h"

bn::sprite_tiles_ptr sprite_tiles = bn::sprite_tiles_items::image.create_tiles();

Sprite palettes

An example of the *.json files required for sprite palettes is the following:

{
    "type": "sprite_palette"
}

The fields for sprite palettes are the following:

  • "type": must be "sprite_palette" for sprites.
  • "compression": optional field which specifies the compression of the colors data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.

If the conversion process has finished successfully, a bn::sprite_palette_item should have been generated in the build folder.

For example, from two files named image.bmp and image.json, a header file named bn_sprite_palette_items_image.h is generated in the build folder.

You can use this header to create a sprite palette with only one line of C++ code:

#include "bn_sprite_palette_items_image.h"

bn::sprite_palette_ptr sprite_palette = bn::sprite_palette_items::image.create_palette();

Regular backgrounds

An image file can contain only one regular background. The size of a small regular background (which are faster) must be 256x256, 256x512, 512x256 or 512x512 pixels. Big regular backgrounds are slower CPU wise and don't support wrapping (they can't be moved beyond their boundaries), but can have any width or height multiple of 256 pixels.

An example of the *.json files required for regular backgrounds is the following:

{
    "type": "regular_bg"
}

The fields for regular backgrounds are the following:

  • "type": must be "regular_bg" for regular backgrounds.
  • "repeated_tiles_reduction": optional field which specifies if repeated tiles must be reduced or not (true by default).
  • "flipped_tiles_reduction": optional field which specifies if flipped tiles must be reduced or not (true by default).
  • "bpp_mode": optional field which specifies the bits per pixel of the regular background:
    • "bpp_8": up to 256 colors per tile.
    • "bpp_4_auto": up to 16 colors per tile. Butano tries to quantize the image to fit the color palette into the required one.
    • "bpp_4_manual": up to 16 colors per tile. Butano expects that the image color palette is already valid for this mode.

The default is "bpp_4_manual" for 16 color images and "bpp_8" for 256 color images.

  • "tiles_compression": optional field which specifies the compression of the tiles data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "palette_compression": optional field which specifies the compression of the colors data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "map_compression": optional field which specifies the compression of the map data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "compression": optional field which specifies the compression of the tiles, the colors and the map data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.

If the conversion process has finished successfully, a bn::regular_bg_item should have been generated in the build folder.

For example, from two files named image.bmp and image.json, a header file named bn_regular_bg_items_image.h is generated in the build folder.

You can use this header to create a regular background with only one line of C++ code:

#include "bn_regular_bg_items_image.h"

bn::regular_bg_ptr regular_bg = bn::regular_bg_items::image.create_bg(0, 0);

Affine backgrounds

An image file can contain only one affine background. The size of a small affine background (which are faster) must be 128x128, 256x256, 512x512 or 1024x1024 pixels. Big affine backgrounds are slower CPU wise and don't support wrapping (they can't be moved beyond their boundaries), but can have any width or height multiple of 256 pixels.

An example of the *.json files required for affine backgrounds is the following:

{
    "type": "affine_bg"
}

The fields for affine backgrounds are the following:

  • "type": must be "affine_bg" for affine backgrounds.
  • "repeated_tiles_reduction": optional field which specifies if repeated tiles must be reduced or not (true by default).
  • "tiles_compression": optional field which specifies the compression of the tiles data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "palette_compression": optional field which specifies the compression of the colors data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "map_compression": optional field which specifies the compression of the map data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.
  • "compression": optional field which specifies the compression of the tiles, the colors and the map data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.

If the conversion process has finished successfully, a bn::affine_bg_item should have been generated in the build folder.

For example, from two files named image.bmp and image.json, a header file named bn_affine_bg_items_image.h is generated in the build folder.

You can use this header to create an affine background with only one line of C++ code:

#include "bn_affine_bg_items_image.h"

bn::affine_bg_ptr affine_bg = bn::affine_bg_items::image.create_bg(0, 0);

Background palettes

An example of the *.json files required for background palettes is the following:

{
    "type": "bg_palette",
    "bpp_mode": "bpp_8"
}

The fields for background palettes are the following:

  • "type": must be "bg_palette" for background palettes.
  • "bpp_mode": specifies the bits per pixel of the background palette:
    • "bpp_8": up to 256 colors per tile.
    • "bpp_4": up to 16 colors per tile.
  • "compression": optional field which specifies the compression of the tiles and the colors data:
    • "none": uncompressed data (this is the default option).
    • "lz77": LZ77 compressed data.
    • "run_length": Run-length compressed data.
    • "auto": uses the option which gives the smallest data size.

If the conversion process has finished successfully, a bn::bg_palette_item should have been generated in the build folder.

For example, from two files named image.bmp and image.json, a header file named bn_bg_palette_items_image.h is generated in the build folder.

You can use this header to create a background palette with only one line of C++ code:

#include "bn_bg_palette_items_image.h"

bn::bg_palette_ptr bg_palette = bn::bg_palette_items::image.create_palette();

Audio

By default audio files go into the audio folder of your project.

Audio stuff is managed by the awesome Maxmod, so if you have an issue with music or sound effects, well, you know.

A really nice application for editing audio files before importing them into your game is OpenMPT.

Music

The required format for music are module files (files with *.mod, *.xm, *.s3m and *.it extensions).

By default Butano supports up to 16 music channels, but this limit can be increased by overloading the definition of BN_CFG_AUDIO_MAX_MUSIC_CHANNELS.

However, if it is possible don't do this, don't make the poor GBA suffer.

If the conversion process has finished successfully, a bunch of bn::music_item objects under the bn::music_items namespace should have been generated in the build folder for all music files. You can use these items to play music with only one line of C++ code:

#include "bn_music_items.h"

bn::music_items::song.play();

Sound effects

The required format for sound effects is waveform audio files (files with *.wav extension) without compression or anything weird. Besides, I think stereo files are not allowed.

The recommended quality for sound effects is 8-bits 22050 Hz.

If the conversion process has finished successfully, a bunch of bn::sound_item objects under the bn::sound_items namespace should have been generated in the build folder for all sound files. You can use these items to play sound effects with only one line of C++ code:

#include "bn_sound_items.h"

bn::sound_items::sfx.play();