UI & Text

Variable-width font rendering, text control codes, overlay window management, dialogue flow, and menu system. The UI and text system is implemented in C.

Variable-Width Font (VWF) System

GB Studio uses a software-rendered variable-width font system, not hardware tile-based text. Characters are drawn into tile buffers at arbitrary pixel offsets, producing proportionally-spaced text on the Game Boy’s 8×8 tile grid.

Font Structure

Each font resource is stored as a banked data block with the following header:

typedef struct font_desc_t {
    UBYTE char_start;      // First character code (usually 32 = space)
    UBYTE char_count;      // Number of characters
    UBYTE char_width;      // Max character width in pixels
    UBYTE char_height;     // Character height in pixels
    UBYTE name_length;     // Length of font name string
    // followed by: name, width table, glyph data
} font_desc_t;

VWF Rendering Pipeline

  1. Characters are drawn into a temporary tile buffer
  2. Each character’s width advances the cursor by a variable amount
  3. When the cursor crosses a tile boundary, the completed tile is written to VRAM
  4. Rendering happens during ui_update() in the main loop
Software rendering

Because VWF is software-rendered, text display is not instantaneous. Characters are drawn progressively across frames during ui_update(), which runs near the end of the main loop. Text speed controls how many characters are rendered per frame.

Text Control Codes

Control codes are embedded within dialogue text strings to modify rendering behavior. They are processed inline as the VWF engine encounters them.

CodeHexDescription
End of string0x00Terminates text
Newline0x01Move to next line
Speed (instant)0x02Set text speed to instant
Speed (value)0x03 + NSet speed to N frames per character
Font change0x04 + bank + addrSwitch to different font
Goto tile0x05 + X + YMove cursor to tile position
Relative goto0x06 + X + YMove cursor relative
Set palette0x07 + PSet text palette (0–7)
Wait for input0x08Pause until button press
Escape next0x09Print next byte literally
Variable ref0x0A + var_hi + var_loInsert variable value as text
Char ref0x0B + var_hi + var_loInsert variable value as character
Speed (fast)0x0CSet fast speed
Clear window0x0DClear text area

Text Palette

The text_palette global variable (UINT8, range 0–7) controls which of the 8 BG palettes is used for rendering text tiles.

Dark backgrounds and text visibility

When displaying text over dark backgrounds, the default palette may not provide sufficient contrast. Use the 0x07 control code or set text_palette before rendering to switch to a palette with light-on-dark colors.

Overlay Window

The Game Boy hardware window layer is used for dialogue boxes, menus, and HUD elements. It is positioned independently of the background scroll and always renders on top of the BG and sprite layers.

Window Registers

Window Management

overlay_cut_scanline not in header

overlay_cut_scanline is defined in interrupts.c but not declared in interrupts.h. If you need to access it from plugin code, add a manual declaration:

extern UBYTE overlay_cut_scanline;

Dialogue System

The dialogue system combines the overlay window with VWF text rendering to display character dialogue, narration, and informational text.

Dialogue Flow

  1. Overlay window slides up from the bottom of the screen
  2. Text renders character-by-character using the VWF engine
  3. Player presses a button to advance to the next text block
  4. Window slides back down when dialogue is complete

GBVM Commands

CommandDescription
VM_DISPLAY_TEXTDisplay text in dialogue box with variable substitution
VM_DISPLAY_TEXT_SET_ANIM_SPEEDSet text animation parameters (speed, delay)
VM_OVERLAY_SHOWShow the overlay window
VM_OVERLAY_HIDEHide the overlay window
VM_OVERLAY_MOVE_TOMove overlay to a specific position
VM_OVERLAY_SET_MAPSet specific tiles in the overlay tile map

Menus are rendered in the overlay window using a combination of text and a cursor sprite to indicate the selected item.

Text Drawing Commands (GBVM)

The full set of GBVM commands related to text and overlay rendering:

CommandDescription
VM_DISPLAY_TEXTRender text with variable substitution
VM_LOAD_TEXTLoad text into buffer (without displaying)
VM_SWITCH_TEXT_FONTChange the active font
VM_OVERLAY_SET_MAPCopy tilemap region to overlay
VM_OVERLAY_SET_SUBMAPCopy submap to overlay (with CGB attributes)

Common Patterns

Setting Text Color for Dark Backgrounds

When dialogue appears over a dark scene, the default text palette (palette 7) may render text invisible. Prepend a palette change control code before the text, or set text_palette globally:

// Use control code 0x07 to change text palette inline
// In event script: prepend palette change before text

// Or set globally before displaying text
text_palette = 3;  // Use BG palette 3 for text

Custom HUD with Overlay

Keep the overlay window visible during gameplay to display persistent HUD information:

// 1. Show overlay at specific position (non-modal so gameplay continues)
VM_OVERLAY_SHOW 0, 0, .UI_COLOR, .UI_NONMODAL

// 2. Write tiles to overlay
VM_OVERLAY_SET_MAP 0, 0, 20, 2, _ui_hud_tilemap

// 3. Overlay remains visible during gameplay
//    Update individual tiles as values change
Modal vs non-modal overlay

Use .UI_NONMODAL when the overlay should remain visible during gameplay (HUDs, status bars). Use the default modal mode for dialogue and menus where player input should be captured by the UI system.