Fonts¶
Crimsonland ships two bitmap fonts:
- Small font (
smallFnt.dat+smallWhite.png): variable-width, 16x16 atlas, used bygrim_draw_text_small. [static] - Grim2D mono font (resource id
0x6f): fixed 16px grid, used bygrim_draw_text_mono. [static]
Small font (smallFnt.dat)¶
Location¶
game_bins/crimsonland/1.9.93-gog/crimson.paq:load\smallFnt.dat,load\smallWhite.tga- Extracted to
artifacts/assets/crimson/load/smallFnt.datandartifacts/assets/crimson/load/smallWhite.png
Layout¶
widths[i] is the glyph advance in pixels for glyph index i (0-255).
The renderer uses the same value to size the UV width.
Atlas + UVs¶
The extracted smallWhite.png (from smallWhite.tga) is 256x256 RGBA. The renderer treats it as a 16x16 grid,
so each glyph cell is 16x16. UV origins are:
The original Direct3D8 renderer applies a small bias of 1/512 to the U/V values to reduce bleeding. The Raylib/OpenGL port intentionally omits that inset because it visibly crops the small-font glyphs on this backend.
Identification (font source)¶
The small font glyphs match Pixel Arial 11. The closest match we found is
PIXEARG_.TTF (often distributed as "Pixel Arial 11"). Reference:
https://www.dafont.com/pixel-arial-11.font
Rendering hooks (grim.dll)¶
grim_init_system(FUN_10005eb0) loadsload\smallFnt.datand copies 0x100 bytes intogrim_font2_glyph_widths.grim_measure_text_width(vtable offset0x14c) sums widths and returns the widest line.grim_draw_text_small(vtable offset0x144) bindsGRIM_Font2and emits quads using the UV math above.grim_font2_char_mapis initialized as an identity lookup table, so glyph index equals the byte value. [static]
Grim2D mono font (grim_draw_text_mono)¶
Source¶
-
grim_draw_text_monobindsgrim_font_texture, which is loaded from Grim2D resources (resource id0x6f). [static] -
This is not yet confirmed to match
default_font_courier.tgafromcrimson.paq. [static]
Behavior¶
- Advance:
16 * scale(fixed). [static] - Cursor origin:
xis treated as a cursor origin; the renderer advances X before drawing each glyph by16 * scale(except when the 0xA7 control code marks the next glyph as “no pre-advance”). [static] - Line height:
28 * scale(newline step). [static] - Draw size:
32 * scalewidth x32 * scaleheight. [static] - Baseline quirk: Most glyph quads are drawn at
y + 1.0(literal +1px, not scaled). [static] - Visual effect: Characters are drawn at 2x the size of their horizontal spacing, creating a dense, tall appearance (effective 1:2 aspect ratio relative to the grid). [static]
- UVs: 16x16 table (
grim_font2_uv_u/v), indexed directly by byte value (grim_font2_char_mapis identity). [static] - Special codes: 0xA7 (skip pre-advance for next glyph), plus 0xE4/0xE5/0xF6 and
\n. [static]
Quest title overlay (runtime evidence)¶
The quest HUD renders the level number and title with separate mono draws:
- Title (
"Land Hostile") uses the base scale (0.75 at 640px width, 0.8 at larger widths). [static+runtime] - Number (
"1.1") usesbase_scale - 0.2(observed 0.55 when base is 0.75). [runtime] - Opacity: number alpha is 50% of title alpha (ratio 0.5 across captures). [runtime]
-
Position X: computed dynamically based on string length: [static]
where8.0is half the font advance (16/2),32.0is the base gap, and4.0is a fixed offset. For "1.1" (3 chars) at scale 0.55:3 * 0.55 * 8 + 0.55 * 32 + 4 = 34.8 px. For "1.10" (4 chars) at scale 0.55:4 * 0.55 * 8 + 0.55 * 32 + 4 = 39.2 px. [static] -
Position Y: computed from number_scale: [static]
where7.36 = 23.36 - 16.0(constants at 0x46f5a0 and 0x46f230). At number_scale 0.55:0.55 * 7.36 = 4.048 pxlower than title. At number_scale 0.60:0.60 * 7.36 = 4.416 pxlower than title. [static]
Evidence: artifacts/frida/share/quest_title_colors.jsonl (quest HUD capture on 2026-01-20). Runtime logs show paired draw_text_mono calls for the title and number with the scale/alpha ratios above. Static analysis of ui_render_hud at 0x41bf94-0x41c01c confirms the dynamic x-position formula using strlen.