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

Display and LCD

The display subsystem turns text, graph buffers, menus, and equation layouts into the 96×64 monochrome image scanned from LCD-controller video RAM. This page maps the OS-facing render paths and software buffers; LCD controller and display bus reconstructs commands, addressing, timing, initialization, reads, power, and controller-revision behavior.

Display paths

The OS uses direct rendering for homescreen text and an explicit RAM back buffer for graphs. [confirmed]

flowchart LR
    TEXT["text and menus"] --> PUT["_PutMap / _VPutMap"]
    PUT --> LCD["controller video RAM"]
    GRAPH["graph rasterizers"] --> BUF["plotSScreen · 0x9340"]
    BUF --> CPY["_GrBufCpy"]
    CPY --> LCD
    LCD --> PANEL["96×64 panel"]
    LCD --> SAVE["_SaveDisp → saveSScreen"]
    SAVE --> RESTORE["_RestoreDisp"]
    RESTORE --> LCD
PathMain entryBehavior
Large text_PutMap at 01:5A98draws one large-font glyph directly into controller RAM
Cooked character_PutC at 01:5B4Ccalls _PutMap, advances curCol, and handles newline/wrap
String_PutS at 01:5C39emits a null-terminated large-font string
Small text_VPutMap/_VPutSrenders variable-width glyphs using penCol/penRow
Graph clear_GrBufClr at 04:6071clears 768 bytes of plotSScreen; does not touch the LCD
Graph blit_GrBufCpy at 04:60A3copies selected graph-buffer rows to controller RAM
Physical clear_ClrLCDFull at 01:60E4writes zero to all 768 visible controller bytes
Save/restore_SaveDisp/_RestoreDispcaptures and restores the displayed image

Software display state

AddressNameSizeRole
0x8447contrast1 byteOS contrast level used to build controller command 0xC00xFF
0x844AcurTime1 bytetimer-driven cursor blink countdown
0x844B/0x844CcurRow/curCol2 bytes16×8 homescreen character cursor
0x845A0x8461lFont_record8 bytescurrent large-font render record
0x85080x8587textShadow128 bytes16×8 homescreen character shadow
0x86EC0x89EBsaveSScreen768 bytessaved display image
0x93400x963FplotSScreen768 bytesgraph/back buffer, 12 bytes × 64 rows

Both 768-byte buffers use the MonoFramebuffer layout: [confirmed]

typedef struct {
    uint8_t rows[64][12];
} MonoFramebuffer;

Each rows[y][byte_column] byte holds eight pixels, most-significant bit first. Controller video RAM is a third image store outside Z80 RAM. Direct text output can change it without changing plotSScreen, while graph drawing can change plotSScreen without changing the panel until _GrBufCpy runs. [confirmed]

LCD-ready wait [confirmed]

_lcd_busy = 0x4051, body ram:0CC3, preserves AF while polling port 0x02 bit 1 until the LCD reports ready. If bit 3 of IY + 0x41 is set after that poll, it calls the short delay helper at ram:0CE6 three times before restoring AF and returning. The ROM has callers in the fixed page and on pages 0x01, 0x04, 0x06, 0x07, 0x39, and 0x3B; it is the common serialization point used before direct LCD operations.

A source-built fixture reaches the body and returns to its marker. That trace confirms the callable path in TilEm, while the port-poll latency and optional three-delay branch remain dependent on emulator or hardware LCD state. The result is pinned in tools/data/community-manual-bcall-traces.csv.

Large-font text

_PutMap clamps character code zero and codes at or above 0xF8 to replacement code 0xD0. It computes character × 8 and bjumps to put_glyph_large at 07:4588. [confirmed]

The page-7 blitter adjusts that offset to a seven-byte packed stride:

$$ \text{glyph address} = \texttt{07:45FF} + 7c $$

where $c$ is the character code. It then copies eight bytes into lFont_record, so the eighth byte overlaps the first byte of the next packed glyph. [confirmed]

Two flags at IY+0x35 select alternate font-hook sources before the page-7 table read. Bit 5 calls 3B:7BFB with selector A=0x01; bit 1 calls 3B:7B9C with selector A=0x76. With neither flag set, _PutMap reads the built-in table. [confirmed]

The renderer positions the controller from curRow and curCol. Glyph edges use controller read-modify-write with the required dummy data read before the real byte. The complete bus sequence is in LCD controller and display bus.

Cursor and indicators

_CursorOn and _CursorOff reload curTime with 50. Standard hardware timer 1 reaches cursor_blink_tick at 06:7C45, which toggles the cursor every 50 ticks. See Clock, timers, and power. [confirmed]

The run indicator uses indicCounter and indicBusy at 0x8476/0x8477. _RunIndicOn seeds it, and run_indicator_tick at ram:027B advances it from the same standard-timer interrupt. _ClrLCDFull temporarily clears and then restores the indicator-enable bit around the physical clear. [confirmed]

Numeric and string output

_DispHL at 01:5BF6 converts HL to five decimal positions with repeated _DivHLBy10, stores digits backward in scratch RAM, replaces leading zeroes with spaces, and prints through _PutC. [confirmed]

_PutC wraps when curCol reaches 16 and calls the newline/scroll path. _PutS and related bounded-string entries repeat _PutC over character data. These APIs target the character-oriented homescreen state, not the graph buffer. [confirmed]

Graph and equation rendering

Graph rasterizers write plotSScreen and call _GrBufCpy or _PDspGrph to expose the result. Coordinate transforms, clipping, line/circle algorithms, and graph state are covered in Graphing.

MathPrint uses a separate layout engine before its glyphs reach the display primitives. Its descriptors, box tree, cursor geometry, and runtime gaps are covered in Equation display.

The table editor and Y= screens build text-grid state through their own context handlers. See Table and Y= variables.

  • LCD controller and display bus — ports, status, commands, addressing, waits, initialization, clear/blit/read paths, contrast, power, dynamic I/O traces, and cross-emulator fidelity.
  • Graphing — graph buffer, transforms, pixels, lines, circles, and graph display.
  • Equation display — MathPrint layout and compositing.
  • Table and Y= variables — table grid and function editor.