Files
YataiDONNijiiro/tools/font/FONT.md
T
YonokidandClaude Sonnet 5 463194ccde Move fonts to dedicated Fonts folder
Keeps font.ttf and per-language font_*.ttf out of Graphics so
texture/atlas tooling doesn't need to skip non-image files.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 12:15:58 -04:00

4.5 KiB
Raw Blame History

Fonts/font.ttf — how it is made, and how the cabinet actually uses its fonts

What the cabinet ships

The cabinet has no vector font. Data\x64\font\ holds pre-rasterised BC7 glyph atlases, one family per language and one atlas per size/weight bucket, each with an XML sidecar (codepoint → rect; no bearings, no kerning):

language buckets on disk distinct codepoints face (as drawn in the atlas)
jp 30, 32_B, 32_DB, 32_EB, 64 7 532 30/32: rounded gothic in three weights; 64: brush/勘亭流-style display face
tw 30, 32, 64 17 678 same split
cn 30, 32, 64 7 608 same split (the 64 face is a heavier brush)
kr 30, 32, 64 8 407 same split
en 30, 32, 64 299 same split

(The JP 39.06 dump has the same files minus cn_*; the CN 05 dump adds cn_*. The jp/tw/kr/en XMLs are byte-identical between the two.)

How a text record picks its atlas

  • Language comes from the cabinet language setting: wordlist rows are looked up in the language's column and rendered from that language's atlas family. Rows flagged fontType 0 (untranslated) always render from jp.
  • Size/weight bucket is authored per text record in the .nulm (DefineFont entry symbol "0".."4" → 64, 30, 32_EB, 32_B, 32_DB). It is not language dependent. For en/tw/kr/cn the three weighted 32_* buckets are registered onto the plain 32 atlas, so a record that asks for 32_EB on a cn cabinet is drawn from cn_32.
  • The only fallback is jp_64 when the language itself is unknown; a codepoint missing from the chosen atlas is simply not drawn. Of the 692 text records in the shipped movies, 449 use the 30/32 (rounded gothic) buckets and 168 use the 64 (brush) bucket.

YataiDON draws every string through a single .ttf, so one face has to serve all of it. This skin's font.ttf is built from the _64 (brush) atlases, which is the face used for headings, song titles and most of the large text.

Building font.ttf

tools/font/build_font.py merges the five _64 atlases into one TrueType font:

  1. Decode each <lang>_64.nutexb to a DDS (BC7, nutexb_dump -o) next to its XML.
  2. For each language in priority order jp, tw, cn, kr, en, every codepoint that does not yet have an inked glyph takes its bitmap from that atlas (blank placeholder cells are skipped so a later atlas can supply the character).
  3. Each bitmap is upscaled 4× (bicubic), thresholded at alpha ≥ 128, traced with potrace and converted to quadratic outlines (cu2qu).
  4. Metrics: unitsPerEm 1024, scale = 1024 / fontPoint of the atlas (16 units per pixel for jp_64), advance = cell width × scale, baseline = the atlas's median bottom ink row of its Han/Hangul glyphs, so the five families sit on one baseline with equal Han height. ascender 880 / descender −144, as the earlier build.
pip install potracer fonttools pillow numpy
python build_font.py <dir with *_64.dds + *_64.xml> font.ttf --order jp,tw,cn,kr,en

Result (version 3.000): 22 382 glyphs — 7 499 from jp, 10 107 from tw, 1 956 from cn, 2 737 from kr, 82 from en. Coverage of each atlas's repertoire: jp 7521/7532, tw 17651/17678, cn 7589/7608, kr 8070/8407, en 268/295 (the remainder are blank cells in the atlases themselves). Version 2.000 had no cn or kr glyphs, which is why Simplified Chinese and Korean text showed ?.

Per-language fonts (Fonts/font_<family>.ttf)

The engine loads Fonts/font_<language code>.ttf if present, else Fonts/font_<cabinet family>.ttf (zh → cn, ko → kr, ja → jp), else font.ttf. The settings screen reloads the skin, so switching language switches the font. This mirrors the cabinet, which draws everything from the language's own atlas family and only lacks what that family does not have.

file atlas priority used for
font.ttf jp, tw, cn, kr, en Japanese, and any language without its own file (unchanged 3.000)
font_cn.ttf cn, tw, jp, en, kr Simplified Chinese (zh)
font_tw.ttf tw, jp, cn, en, kr Traditional Chinese (zh_tw / tw)
font_en.ttf en, jp, tw, cn, kr English
font_kr.ttf kr, jp, en, tw, cn Korean (ko)
python build_font.py <dir> font_cn.ttf --order cn,tw,jp,en,kr
python build_font.py <dir> font_tw.ttf --order tw,jp,cn,en,kr
python build_font.py <dir> font_en.ttf --order en,jp,tw,cn,kr
python build_font.py <dir> font_kr.ttf --order kr,jp,en,tw,cn