This program was created entirely using GPT-5.3-Codex without writing code by hand.
CLI utility for converting Westwood Unicode BitFont (game.fnt, fonT), a font format used in Command & Conquer: Red Alert 2, to a PNG set and back.
go build ./src/cmd/ra2fntLocal multi-platform release build scripts:
./scripts/build-release.sh
./scripts/build-release.sh v1.0.0powershell -ExecutionPolicy Bypass -File .\scripts\build-release.ps1
powershell -ExecutionPolicy Bypass -File .\scripts\build-release.ps1 -Version v1.0.0scripts\build-release.bat
scripts\build-release.bat v1.0.0Export .fnt to PNG set:
./ra2fnt export -in game.fnt -out out_fontExport with integer pixel scaling (for easier editing):
./ra2fnt export -in game.fnt -out out_font --scale 3Non-interactive overwrite for scripts/CI:
./ra2fnt export -in game.fnt -out out_font --forceCreate .fnt from PNG set:
./ra2fnt create -in out_font -out rebuilt.fntCreate without glyph deduplication:
./ra2fnt create -in out_font -out rebuilt.fnt --no-dedupValidate PNG set and metadata without writing .fnt:
./ra2fnt validate -in out_fontShow CLI version:
./ra2fnt version
./ra2fnt --versionexport and create show a progress bar in stderr.
If out directory already exists, export asks for confirmation before deleting it.
- Use
--forceto skip confirmation and overwriteout.
export writes only PNG files grouped by Unicode ranges:
out_font/
metadata.json
0x0020-0x007F (Basic Latin)/
0x0041.png
0x0042.png
0x0400-0x04FF (Cyrillic)/
0x0451.png
In this tree, only non-zero-width glyphs are shown as PNG files.
Zero-width glyphs are listed only in metadata.json (symbol_width).
- One PNG is exported per mapped Unicode codepoint from the
.fntunicode table. - PNG filename is fixed-length hex codepoint:
0xXXXX.png. metadata.jsonstores:symbol_width(only zero-width glyphs, as0)symbol_stridefont_heightideograph_widthscale(integer export scale, default1)
- Zero-width glyphs are not exported as PNG files and are restored via
metadata.json(symbol_width=0). - PNG height is
symbol_height. - No
unicode_table.binortail.binis produced.
create reconstructs a .fnt from PNG files in the input directory:
- PNG files are discovered recursively (subdirectory names are ignored by parser).
- Files must be named as fixed-length hex codepoints (for example
0x0041.png,0x30A1.png). - Zero-width glyphs are restored from
metadata.json(symbol_width=0). - Codepoints with
symbol_width=0must not have PNG files. - All PNG files must have the same height.
symbol_widthcontains only zero-width entries and is used to restore width0; otherwise width is taken from PNG width.symbol_strideis taken frommetadata.jsonwhen present; otherwise it is auto-calculated asceil(max_symbol_width / 8).font_heightis taken frommetadata.json.ideograph_widthis taken frommetadata.json.scaleis taken frommetadata.json; whenscale > 1, PNG dimensions are downscaled by this factor duringcreate(back to normal font size).- Identical glyphs are deduplicated, so multiple codepoints can reference the same symbol index.
- Use
--no-dedupto disable deduplication. - Unicode table is rebuilt from filenames (
0xXXXX-> symbol index in sorted codepoint order).
Because unicode mapping order/tail bytes are rebuilt, the resulting .fnt is not expected to be byte-identical to the original input file.
validate runs the same checks as create without writing output .fnt, and prints a summary:
- total codepoints
- number of PNG files
- number of zero-width codepoints from metadata
- resulting symbol count
- number of deduplicated symbols
- Output
.fntis not byte-identical to sourcegame.fnt. - At least one non-zero-width PNG is required to infer
symbol_height. - Zero-width glyphs are represented only in
metadata.jsonand have no PNG files. - Unicode table order is rebuilt from sorted codepoints.