gba_agb_font_renderer 0.6.0

Bitmap font renderer for GBA/AGB
docs.rs failed to build gba_agb_font_renderer-0.6.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Crates.io Documentation

Bitmap Font for GBA/AGB

Renderer for bitmap fonts on the GBA using the agb framework

Font converter

Use the AGB Font Converter to convert images to fonts and for loading fonts from images via macro

Usage

In Cargo.toml gba_agb_font_renderer = "0.6.0"

Loading a font

[!TIP] Use the macro from https://crates.io/crates/gba_agb_font_loader instead of these

Two font types are available: FullFont (all 256 code points) and PrintableFont (95 printable ASCII chars, 0x20–0x7E). Load them at compile time with the corresponding macro:

use gba_agb_font_renderer::prelude::*;

// Full 256-char font from ROM (default)
let font = full_font!(include_bytes!("my_font.bin"));

// Printable ASCII font, placed in IWRAM for faster blitting
// (~8× fewer waitstates per pixel row — only worthwhile for printable fonts ~3 KB)
let font = printable_font!(include_bytes!("my_font.bin"), iwram);

// Full 256-char font placed in EWRAM
let font = full_font!(include_bytes!("my_font.bin"), ewram);

Rendering text

use gba_agb_font_renderer::prelude::*;
use agb::fixnum::vec2;

let format = TextFormat::new(TextOverflow::Wrap(200, true), TextAlign::Left, (0, 0));
let mut renderer = TextRenderer::default();
renderer.draw_text(b"Hello, world!", &font, &mut bg, vec2(8, 16), &format);

Typewriter effect

TypewriterRenderer reveals text one chunk at a time. Call update() once per frame and draw() to blit newly revealed characters.

use gba_agb_font_renderer::prelude::*;
use agb::fixnum::vec2;

let format = TextFormat::new(TextOverflow::Wrap(200, true), TextAlign::Left, (0, 0));
// 1 character revealed every 2 frames
let mut tw = TypewriterRenderer::new(1, 2, &format);
tw.load_text(b"Hello, world!", vec2(8, 16));

loop {
    tw.update();
    tw.draw(&font, &mut bg, 15);
    if tw.is_complete() { break; }
    vblank.wait_for_vblank();
}

To clear the text area before loading new text:

tw.clear(&font);
tw.load_text(b"New message", vec2(8, 16));

Multiple typewriter streams

MultiTypewriterRenderer manages several independent text streams over a single shared tile pool. Each stream gets a slot index returned by add_text.

use gba_agb_font_renderer::prelude::*;
use agb::fixnum::vec2;

let name_format = TextFormat::default();
let dialog_format = TextFormat::new(TextOverflow::Wrap(200, true), TextAlign::Left, (0, 0));

// default: 1 char revealed every 2 frames
let mut mtw = MultiTypewriterRenderer::new(2, 1);
mtw.add_text(SlotFont::from(&NAME_FONT), b"Hero", vec2(8, 8), &name_format);
let dialog = mtw.add_text(SlotFont::from(&DIALOG_FONT), b"Hello, world!", vec2(8, 24), &dialog_format);

loop {
    mtw.update();
    mtw.draw(&mut bg, 15);
    if mtw.is_complete() { break; }
    vblank.wait_for_vblank();
}
mtw.clear_all();

Font binary format

Two modes are supported, selected by the mode byte at offset 0.

Common header

Offset Size Field
0 1 mode0 = printable ASCII, 1 = all-256
1 1 glyph_width — glyph cell width in pixels
2 1 glyph_height — glyph cell height in pixels

Mode 0 — printable ASCII (95 glyphs)

Offset Size Field
3 95 char_widths — advance width per character, ascending byte order
98 2 padding to 4-byte boundary
100 varies 4bpp pixel data

Mode 1 — all-256 (256 glyphs)

Offset Size Field
3 256 char_widths — advance width per code point
259 1 padding to 4-byte boundary
260 varies 4bpp pixel data

Pixel data

Stored as u32 values, each holding 8 pixels at 4 bits per pixel (4bpp). Each glyph row occupies (glyph_width + 7) / 8 u32s. Palette index 0 is transparent.