Skip to main content
← PSoXide SDK guides and examples · SDK f2fec1c301f1 · All Cargo features enabled; check feature gates before use.

Crate psx_font

Crate psx_font 

Source
Expand description

Bitmap-font atlases for the PS1.

One crate, two types, three steps:

  1. Declare (or pick) a BitmapFont – a static descriptor that carries glyph dimensions, a 1-bit-per-pixel bitmap, and layout metadata (advance, line height, bit order). The built-in fonts in fonts cover Public-Domain IBM-VGA-style 8×8 for ASCII / Latin-1 / box-drawing.

  2. 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.

  3. Call one of the FontAtlas draw 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

MethodHardwareCost / glyphDoes
FontAtlas::draw_textGP0 0x64 textured rect4 words1:1 axis-aligned, single tint
FontAtlas::draw_text_scaledGP0 0x2C textured quad9 wordsInteger scale (2×, 3×, …), single tint
FontAtlas::draw_text_scaled_q8GP0 0x2C textured quad9 wordsQ8 fractional scale (1.5× = 384), single tint
FontAtlas::draw_text_rotatedGP0 0x2C textured quad9 wordsArbitrary angle rotation, single tint
FontAtlas::draw_text_affineGP0 0x2C textured quad9 wordsArbitrary 2×2 matrix, single tint
FontAtlas::draw_text_gradientGP0 0x3C gouraud-textured quad12 words1:1, top/bottom gradient
FontAtlas::draw_text_scaled_gradientGP0 0x3C gouraud-textured quad12 wordsScaled + 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_row so the atlas fits within its tpage.
  • Upload buffer: the stack-only scratch buffer inside FontAtlas::upload is 16 KiB, enough for 128 glyphs at 16×16 or 64 glyphs at 32×16. Larger atlases panic today; use upload_fonts with 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: origin is 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 to origin.

§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§

fonts
Built-in fonts.
hex
Heap-free hex label formatting for debug HUDs.

Structs§

BitmapFont
A bitmap font as a static data descriptor.
FontAtlas
A BitmapFont installed in VRAM and ready to draw from.
FontPackMetrics
VRAM and scratch requirements for one packed font-set upload.
FontSetVram
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.
TextBlend
GPU semi-transparency equation for FontAtlas::draw_text_blended.

Traits§

TextSink
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_fonts without reserving VRAM or touching the GPU.
upload_fonts
Upload several fonts in a single GP0(A0h) image transfer.