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 B × 200 / 256 (integer); A does not enter either alpha. Glide draws each copy with that value as the constant colour’s alpha. Values below 254 blend over the scene (source alpha, one minus source alpha); 254 and above draw without blending.
  • 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.

Shared text colour state

The Glide text colour setup does not select a palette. For a font with its indexed-colour flag set, it reads the current text-colour index from the already selected palette and writes those RGB components to the constant colour state. The constant alpha is the font’s first style value, A. For a font without that flag, all four constant colour components are set to A instead. These are the text setup values; individual glyph and shadow passes apply the rules above.

The text colour reset sets all four constant colour components to 255. It does not restore an earlier constant colour or change the selected palette.

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.