ZX Typer

This file is part of Timex Sinclair Public Domain Library Tape 1002 . Download the collection to get this file.
Developer(s): Ryan Gray
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Banner

This program renders user-input text as large block-graphic characters, three display rows tall, using the ZX Spectrum’s block graphics (chars 128–143). After accepting a string via INPUT, it iterates through each character, dispatches to a subroutine via the computed GOSUB formula (CODE A$(A)-25)*100, and draws the corresponding block-graphic glyph at position (X,Y) on screen. Characters are laid out in a grid of 3-row-high cells, advancing Y by 3 each step and wrapping to the next row (incrementing X by 3) after every 10 characters. The program covers letters and digits, with each glyph defined by three PRINT AT statements using block graphics to approximate each character’s shape.


Program Analysis

Program Structure

The program is organised into three logical areas:

  1. Initialisation and input (lines 10–93): REMs serve as a title banner (displaying “ZX-TYPER” in inverse video). Lines 20–24 initialise cursor positions and accept a string, capping its length at 70 characters.
  2. Main loop (lines 30–93): Iterates over each character of the input string, skips spaces and low punctuation, computes a subroutine address, draws the glyph, and advances the layout cursor.
  3. Glyph subroutines (lines 200–3803): Each subroutine draws a single block-graphic character using three PRINT AT statements, then RETURNs. Subroutine numbers are multiples of 100, and the dispatch formula maps ASCII codes directly to them.

Dispatch Mechanism

The key idiom is at line 60:

GOSUB (CODE A$(A)-25)*100

This translates a character’s ASCII code into a subroutine line number. For example, the space character (ASCII 32) gives (32−25)×100 = 700, which is the subroutine for the letter corresponding to that slot. The mapping is:

CharacterASCIIFormula resultSubroutine
!33800line 800
34900line 900
0–948–572300–3200lines 2300–3200
A–Z65–904000–6500(not all present)

In practice, examining the subroutines present (200 through 3803), the covered range maps to punctuation and digits. The letter subroutines starting at line 200 correspond to the . character (ASCII 46, giving (46−25)×100 = 2100), and so on. The actual character set rendered covers roughly . through Z in ASCII order, one subroutine per character.

Layout and Cursor Management

Two variables, X and Y, track the current glyph position on screen. Each glyph occupies a 3×3 block-graphics cell. After drawing each character, Y is incremented by 3 (line 70). When Y reaches 30 — the right edge of the 32-column display at this granularity — it wraps to 0 and X advances by 3 (lines 80–83), moving down to the next row of glyphs. This allows up to 10 glyphs per row and multiple rows.

Input Filtering

Lines 40 and 50 handle character filtering:

  • Line 40 skips space characters entirely (GOTO 70 advances Y without drawing).
  • Line 50 skips any character with ASCII code below . (46) but above space (32) — i.e., punctuation characters ! through - — by executing NEXT A directly, skipping both the GOSUB and the Y-advance. This means those characters are silently ignored rather than advancing the cursor.

Note that line 50’s skip via NEXT A bypasses the Y-increment at line 70, so ignored characters do not consume layout space, which may or may not be the intended behaviour.

Glyph Rendering with Block Graphics

Each glyph subroutine uses two or three PRINT AT X+row, Y+col; "..." statements. The strings contain ZX Spectrum block graphic characters (codes 128–143), which each encode a 2×2 pixel pattern within a single character cell. By combining these, each glyph is rendered at approximately 6×6 pixel resolution across a 3-row, 3-column region of the text screen.

Some glyphs use offset column positions (e.g., PRINT AT X+2,Y+1) to handle narrower characters such as 1, I, and !.

Notable Techniques

  • Computed GOSUB: Using an arithmetic expression as the GOSUB target is an efficient alternative to a long IF-THEN chain for character dispatch.
  • Input loop: After rendering, lines 91–93 wait for another INPUT, clear the screen with CLS, then RUN restarts the program, resetting X and Y to zero for a fresh display.
  • Title in REMs: Lines 10–12 display a bordered title “ZX-TYPER” using inverse-video characters purely as documentation/display in the program listing.
  • String length cap: Line 24 clamps input to 70 characters, preventing the layout loop from overrunning screen bounds.

Anomalies and Notes

  • Line 1400 skips from statement 1400 to 1402 — line 1401 is absent. This is harmless as subroutine execution falls through sequentially, but the missing line number is unusual.
  • The Y=30 wrap condition (line 80) allows 10 three-column glyphs per row (columns 0, 3, 6, …, 27), but with the 3-column glyph width the last glyph starts at column 27 and prints up to column 29, fitting within the 32-column display.
  • Lines 3810–3820 (SAVE "1010%3" followed by RUN) appear at the end of the glyph table and are not part of the normal execution flow; they are used to save the program.
  • The author credit appears as an inverse-video REM at line 9999: “RYAN GRAY”.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10051 – 10121.

Related Products

Related Articles

Related Content

Image Gallery

ZX Typer

Source Code

  10 REM % % % % % % % % % % 
  11 REM % %Z%X%-%T%Y%P%E%R% 
  12 REM % % % % % % % % % % 
  20 LET X=0
  21 LET Y=0
  22 INPUT A$
  23 LET C=LEN A$
  24 IF C>70 THEN LET C=70
  30 FOR A=1 TO C
  40 IF A$(A)=" " THEN GOTO 70
  50 IF A$(A)<"." AND A$(A)>" " THEN NEXT A
  60 GOSUB (CODE A$(A)-25)*100
  70 LET Y=Y+3
  80 IF Y=30 THEN GOTO 82
  81 GOTO 90
  82 LET Y=0
  83 LET X=X+3
  90 NEXT A
  91 INPUT A$
  92 CLS 
  93 RUN 
 200 PRINT AT X+2,Y+1;"\' "
 201 RETURN 
 300 PRINT AT X,Y;"\.'\':\. "
 301 PRINT AT X+1,Y;"\:.\' \: "
 302 PRINT AT X+2,Y;"\ '\''"
 311 RETURN 
 400 PRINT AT X,Y;"\ .\: "
 401 PRINT AT X+1,Y+1;"\: "
 402 PRINT AT X+2,Y;"\ '\''"
 406 RETURN 
 500 PRINT AT X,Y;"\.'\''\. "
 501 PRINT AT X+1,Y;"\ .\''"
 502 PRINT AT X+2,Y;"\''\''\' "
 511 RETURN 
 600 PRINT AT X,Y;"\.'\''\. "
 601 PRINT AT X+1,Y;"\. \''\. "
 602 PRINT AT X+2,Y;"\ '\''"
 610 RETURN 
 700 PRINT AT X,Y;"\ .\':"
 701 PRINT AT X+1,Y;"\:.\.:\. "
 702 PRINT AT X+2,Y+1;"\ '"
 707 RETURN 
 800 PRINT AT X,Y;"\:'\''\' "
 801 PRINT AT X+1,Y;"\''\''\. "
 802 PRINT AT X+2,Y;"\''\''"
 808 RETURN 
 900 PRINT AT X,Y;"\.'\''"
 901 PRINT AT X+1,Y;"\:'\''\. "
 902 PRINT AT X+2,Y;"\ '\''"
 907 RETURN 
\n1000 PRINT AT X,Y;"\''\''\: "
\n1001 PRINT AT X+1,Y+1;"\.'"
\n1002 PRINT AT X+2,Y;"\ '"
\n1005 RETURN 
\n1100 PRINT AT X,Y;"\.'\''\. "
\n1101 PRINT AT X+1,Y;"\.'\''\. "
\n1102 PRINT AT X+2,Y;"\ '\''"
\n1109 RETURN 
\n1200 PRINT AT X,Y;"\.'\''\. "
\n1201 PRINT AT X+1,Y;"\ '\''\: "
\n1202 PRINT AT X+2,Y;"\ '\''"
\n1207 RETURN 
\n1300 PRINT AT X,Y;"\.'\''\. "
\n1301 PRINT AT X+1,Y;"\:'\''\: "
\n1302 PRINT AT X+2,Y;"\'  \' "
\n1303 RETURN 
\n1400 PRINT AT X,Y;"\:'\''\. "
\n1402 PRINT AT X+1,Y;"\:'\''\. "
\n1403 PRINT AT X+2,Y;"\''\''"
\n1409 RETURN 
\n1500 PRINT AT X,Y;"\.'\''\. "
\n1501 PRINT AT X+1,Y;"\:  \. "
\n1502 PRINT AT X+2,Y;"\ '\''"
\n1507 RETURN 
\n1600 PRINT AT X,Y;"\:'\''\. "
\n1601 PRINT AT X+1,Y;"\:  \: "
\n1602 PRINT AT X+2,Y;"\''\''"
\n1608 RETURN 
\n1700 PRINT AT X,Y;"\:'\''\' "
\n1701 PRINT AT X+1,Y;"\:'\''"
\n1702 PRINT AT X+2,Y;"\''\''\' "
\n1707 RETURN 
\n1800 PRINT AT X,Y;"\:'\''\' "
\n1801 PRINT AT X+1,Y;"\:'\''"
\n1802 PRINT AT X+2,Y;"\' "
\n1803 RETURN 
\n1900 PRINT AT X,Y;"\.'\''\' "
\n1901 PRINT AT X+1,Y;"\: \''\: "
\n1902 PRINT AT X+2,Y;"\ '\''\' "
\n1903 RETURN 
\n2000 PRINT AT X,Y;"\:  \: "
\n2001 PRINT AT X+1,Y;"\:'\''\: "
\n2002 PRINT AT X+2,Y;"\'  \' "
\n2003 RETURN 
\n2100 PRINT AT X,Y;"\ '\:'"
\n2101 PRINT AT X+1,Y+1;"\: "
\n2102 PRINT AT X+2,Y;"\ '\''"
\n2103 RETURN 
\n2200 PRINT AT X,Y+2;"\: "
\n2201 PRINT AT X+1,Y;"\.  \: "
\n2202 PRINT AT X+2,Y;"\ '\''"
\n2203 RETURN 
\n2300 PRINT AT X,Y;"\: \ .\' "
\n2301 PRINT AT X+1,Y;"\:'\'."
\n2302 PRINT AT X+2,Y;"\'  \' "
\n2303 RETURN 
\n2400 PRINT AT X,Y;"\: "
\n2401 PRINT AT X+1,Y;"\: "
\n2402 PRINT AT X+2,Y;"\''\''\' "
\n2403 RETURN 
\n2500 PRINT AT X,Y;"\:.\ .\: "
\n2501 PRINT AT X+1,Y;"\: \' \: "
\n2502 PRINT AT X+2,Y;"\'  \' "
\n2503 RETURN 
\n2600 PRINT AT X,Y;"\:. \: "
\n2601 PRINT AT X+1,Y;"\: \'.\: "
\n2602 PRINT AT X+2,Y;"\'  \' "
\n2603 RETURN 
\n2700 PRINT AT X,Y;"\.'\''\. "
\n2701 PRINT AT X+1,Y;"\:  \: "
\n2702 PRINT AT X+2,Y;"\ '\''"
\n2703 RETURN 
\n2800 PRINT AT X,Y;"\:'\''\. "
\n2801 PRINT AT X+1,Y;"\:'\''"
\n2802 PRINT AT X+2,Y;"\' "
\n2803 RETURN 
\n2900 PRINT AT X,Y;"\.'\''\. "
\n2901 PRINT AT X+1,Y;"\: \'.\' "
\n2902 PRINT AT X+2,Y;"\ '\' \' "
\n2903 RETURN 
\n3000 PRINT AT X,Y;"\:'\''\. "
\n3001 PRINT AT X+1,Y;"\:'\':"
\n3002 PRINT AT X+2,Y;"\'  \' "
\n3003 RETURN 
\n3100 PRINT AT X,Y;"\.'\''"
\n3101 PRINT AT X+1,Y;"\ '\''\. "
\n3102 PRINT AT X+2,Y;"\ '\''"
\n3103 RETURN 
\n3200 PRINT AT X,Y;"\''\:'\' "
\n3201 PRINT AT X+1,Y+1;"\: "
\n3202 PRINT AT X+2,Y+1;"\' "
\n3203 RETURN 
\n3300 PRINT AT X,Y;"\:  \: "
\n3301 PRINT AT X+1,Y;"\:  \: "
\n3302 PRINT AT X+2,Y;"\ '\''"
\n3303 RETURN 
\n3400 PRINT AT X,Y;"\:  \: "
\n3401 PRINT AT X+1,Y;"\ :\ :"
\n3402 PRINT AT X+2,Y+1;"\' "
\n3403 RETURN 
\n3500 PRINT AT X,Y;"\:  \: "
\n3501 PRINT AT X+1,Y;"\: \: \: "
\n3502 PRINT AT X+2,Y;"\ '\ '"
\n3503 RETURN 
\n3600 PRINT AT X,Y;"\'.\ .\' "
\n3601 PRINT AT X+1,Y;"\ .\'."
\n3602 PRINT AT X+2,Y;"\'  \' "
\n3603 RETURN 
\n3700 PRINT AT X,Y;"\'.\ .\' "
\n3701 PRINT AT X+1,Y+1;"\: "
\n3702 PRINT AT X+2,Y+1;"\' "
\n3703 RETURN 
\n3800 PRINT AT X,Y;"\''\':\' "
\n3801 PRINT AT X+1,Y;"\ .\' "
\n3802 PRINT AT X+2,Y;"\''\''\' "
\n3803 RETURN 
\n3810 SAVE "1010%3"
\n3820 RUN 
\n9999 REM % %R%Y%A%N% %G%R%A%Y% 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top