Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Subtitles

Spoken dialogue and combat taunts draw their text in FONTS\REDSEL.FNT on a virtual 640×480 screen, which the Glide renderer scales to the output size.

Glyphs

  • Advance per character: glyph width + 1. A space additionally adds the width of !, so a REDSEL space advances 11 pixels. Disabled glyphs advance 0 and are not drawn.
  • A glyph is drawn at (pen x + offset_left, line top + offset_top). Palette index 0 is transparent.
  • Each glyph is drawn twice: first a shadow copy offset by (1, 1), then the main copy.
  • Copies of REDSEL differ only in a value pair A,B: NPC lines use SYSTEM.INI [3dfx] font_sel (shipped 255,255), Cyrus’ lines font_norm (125,255). The main copy is drawn with alpha B, the shadow copy with alpha A × 200 / 256 (integer).
  • For NPC lines using font_sel, main glyphs are opaque in the font’s own palette colours. BPAL entries are 6-bit; index 195 39,3,14 is crimson and index 81 60,59,11 is yellow. The shadow is the glyph shape in black, blended over the scene at alpha 199/255.
  • A line is centred on x = 320: it starts at 320 + trunc(−width / 2).
  • Subtitles ignore [system] disable_text.

Dialogue

The text is the RTX entry’s own string: the label of a voiced entry, the text of a string-only entry. Script functions RTX, rtxAnim and RTXpAnim (speaker: the scripted actor), RTXp (speaker: Cyrus) and combat taunts create subtitles.

Slots

[dialog] dialog_max_dialog_lines is the number of subtitle slots, at least 16 (shipped 20), not a line limit. Slot 0 belongs to Cyrus (RTXp) and is overwritten unconditionally; other speakers take the lowest free slot, and no subtitle is created when none is free. Only one subtitle is drawn per frame: the lowest active slot.

Wrapping

Width limit W = max([dialog] dialog_max_text_width, 150) (shipped 500), measured with REDSEL advances. The text is split into tokens, each an optional leading space plus a word. A token joins the line while running + token < W (strict); otherwise a line break replaces its leading space and the running width restarts at the token’s width including the dropped space.

Position

With breaks line breaks, the block height is 26 × (max(breaks, 1) + 1) and the first line’s top is 470 − height; each next line is 26 lower. One line therefore sits at y 418, two lines at 418 and 444.

Timing

  • dialog_use_speech = 1: a voiced line shows while its clip plays and is freed when the clip stops. A string-only entry is neither drawn nor freed.
  • dialog_use_speech = 0: the voice is stopped. The line starts with remaining = clip seconds × 256 (voiced) or characters × 15 (string-only) and loses 21 per game tick; it is freed once remaining ≤ 0.
  • dialog_print_text = 0: slots keep the same timing (script waits are unchanged) but nothing is drawn.
  • Script RTX lines from a speaker farther than dialog_max_distance (1600) are not started.

Movies

Movie subtitles are documented in movies.