Expand description
Bitmap-font atlases for the PS1.
One crate, two types, three steps:
-
Declare (or pick) a
BitmapFont– astaticdescriptor that carries glyph dimensions, a 1-bit-per-pixel bitmap, and layout metadata (advance, line height, bit order). The built-in fonts infontscover Public-Domain IBM-VGA-style 8×8 for ASCII / Latin-1 / box-drawing. -
Upload it into VRAM once with
FontAtlas::upload– the crate picks a sensible atlas layout, expands the 1bpp source into a 4bpp CLUT texture, uploads that + a two-entry CLUT (transparent + white), and returns a handle. -
Call one of the
FontAtlasdraw methods every frame. The same atlas supports both the fast rectangle path and the flexible quad path – choose based on what the call needs.
§Draw-path cheat sheet
| Method | Hardware | Cost / glyph | Does |
|---|---|---|---|
FontAtlas::draw_text | GP0 0x64 textured rect | 4 words | 1:1 axis-aligned, single tint |
FontAtlas::draw_text_scaled | GP0 0x2C textured quad | 9 words | Integer scale (2×, 3×, …), single tint |
FontAtlas::draw_text_scaled_q8 | GP0 0x2C textured quad | 9 words | Q8 fractional scale (1.5× = 384), single tint |
FontAtlas::draw_text_rotated | GP0 0x2C textured quad | 9 words | Arbitrary angle rotation, single tint |
FontAtlas::draw_text_affine | GP0 0x2C textured quad | 9 words | Arbitrary 2×2 matrix, single tint |
FontAtlas::draw_text_gradient | GP0 0x3C gouraud-textured quad | 12 words | 1:1, top/bottom gradient |
FontAtlas::draw_text_scaled_gradient | GP0 0x3C gouraud-textured quad | 12 words | Scaled + top/bottom gradient |
draw_text is the fast default. Everything below it is a quad
primitive that pays ~2–3× the GP0 bandwidth for transforms or
per-corner colour. At PS1 scale, this matters for text-heavy UIs
(credit crawls, RPG dialogue walls) and doesn’t for a HUD of a
few dozen glyphs. Callers pick consciously.
All methods share the same atlas and CLUT – no duplicate VRAM.
draw_text_* variants can freely mix in one frame, and tints
compose with the PSX per-texel multiplier (output = texel * tint / 128).
§Generic over glyph dimensions
Nothing in BitmapFont or FontAtlas hard-codes 8×8.
Declare a second font at 6×12 or 8×16, drop it into VRAM at a
different tpage, and you can mix sizes on the same screen.
What’s size-dependent:
- Atlas layout: the uploader picks
glyphs_per_rowso the atlas fits within its tpage. - Upload buffer: the stack-only scratch buffer inside
FontAtlas::uploadis 16 KiB, enough for 128 glyphs at 16×16 or 64 glyphs at 32×16. Larger atlases panic today; useupload_fontswith caller-owned scratch for them.
§Why 4bpp and not 15bpp direct
4bpp uses 1/4 the VRAM of 15bpp and opens the standard PSX “colour a monochrome glyph via tint” trick. A 96-glyph ASCII 8×8 atlas fits in 6×8 halfwords = 96 halfwords = 192 bytes of VRAM. Direct-15bpp would be 768 bytes, and you’d lose the free recolouring.
§Coordinate conventions
draw_text/draw_text_scaled/draw_text_gradient:(x, y)is the top-left of the string’s first glyph.draw_text_rotated:(cx, cy)is the rotation pivot – the centre of the baseline. Positive angles rotate counter-clockwise in screen coords.draw_text_affine:originis the point the 2×2 transform maps to the top-left of the first glyph. The matrix is applied in glyph-local space before translating toorigin.
§Fixed-point conventions (rotation + affine)
Rotation uses a Q0.12 angle: u16 in [0, 4096) mapping to
[0°, 360°). Sin/cos come from the shared SDK sin LUT in
[psx_math::sincos] – see that crate for the precision /
Q-format specifics.
Affine matrices are Q3.12 – i16 with 12 fractional bits, so
4096 = 1.0, -4096 = -1.0, 8192 = 2.0, and the usable
range is ±7.999…. That’s enough headroom for any visually
reasonable 2×2 transform a bitmap font would want.
Re-exports§
pub use hex::format_u16;pub use hex::HexU16;
Modules§
Structs§
- Bitmap
Font - A bitmap font as a static data descriptor.
- Font
Atlas - A
BitmapFontinstalled in VRAM and ready to draw from. - Font
Pack Metrics - VRAM and scratch requirements for one packed font-set upload.
- Font
SetVram - VRAM reservations backing a set of fonts uploaded together by
upload_fonts. Free both handles through the allocator to reclaim the VRAM when the owning scene is torn down.
Enums§
- BitOrder
- Bit-packing convention within each bitmap byte.
- Text
Blend - GPU semi-transparency equation for
FontAtlas::draw_text_blended.
Traits§
- Text
Sink - The minimum a widget needs from a text renderer: draw a run at a position in a colour, and measure it.
Functions§
- font_
pack_ metrics - Return the page-run and scratch requirements for
upload_fontswithout reserving VRAM or touching the GPU. - upload_
fonts - Upload several fonts in a single
GP0(A0h)image transfer.