ZX Typer

This file is part of and 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

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 
 1000 PRINT AT X,Y;"'''': "
 1001 PRINT AT X+1,Y+1;".'"
 1002 PRINT AT X+2,Y;" '"
 1005 RETURN 
 1100 PRINT AT X,Y;".'''. "
 1101 PRINT AT X+1,Y;".'''. "
 1102 PRINT AT X+2,Y;" '''"
 1109 RETURN 
 1200 PRINT AT X,Y;".'''. "
 1201 PRINT AT X+1,Y;" ''': "
 1202 PRINT AT X+2,Y;" '''"
 1207 RETURN 
 1300 PRINT AT X,Y;".'''. "
 1301 PRINT AT X+1,Y;":''': "
 1302 PRINT AT X+2,Y;"'  ' "
 1303 RETURN 
 1400 PRINT AT X,Y;":'''. "
 1402 PRINT AT X+1,Y;":'''. "
 1403 PRINT AT X+2,Y;"''''"
 1409 RETURN 
 1500 PRINT AT X,Y;".'''. "
 1501 PRINT AT X+1,Y;":  . "
 1502 PRINT AT X+2,Y;" '''"
 1507 RETURN 
 1600 PRINT AT X,Y;":'''. "
 1601 PRINT AT X+1,Y;":  : "
 1602 PRINT AT X+2,Y;"''''"
 1608 RETURN 
 1700 PRINT AT X,Y;":'''' "
 1701 PRINT AT X+1,Y;":'''"
 1702 PRINT AT X+2,Y;"''''' "
 1707 RETURN 
 1800 PRINT AT X,Y;":'''' "
 1801 PRINT AT X+1,Y;":'''"
 1802 PRINT AT X+2,Y;"' "
 1803 RETURN 
 1900 PRINT AT X,Y;".'''' "
 1901 PRINT AT X+1,Y;": '': "
 1902 PRINT AT X+2,Y;" '''' "
 1903 RETURN 
 2000 PRINT AT X,Y;":  : "
 2001 PRINT AT X+1,Y;":''': "
 2002 PRINT AT X+2,Y;"'  ' "
 2003 RETURN 
 2100 PRINT AT X,Y;" ':'"
 2101 PRINT AT X+1,Y+1;": "
 2102 PRINT AT X+2,Y;" '''"
 2103 RETURN 
 2200 PRINT AT X,Y+2;": "
 2201 PRINT AT X+1,Y;".  : "
 2202 PRINT AT X+2,Y;" '''"
 2203 RETURN 
 2300 PRINT AT X,Y;":  .' "
 2301 PRINT AT X+1,Y;":''."
 2302 PRINT AT X+2,Y;"'  ' "
 2303 RETURN 
 2400 PRINT AT X,Y;": "
 2401 PRINT AT X+1,Y;": "
 2402 PRINT AT X+2,Y;"''''' "
 2403 RETURN 
 2500 PRINT AT X,Y;":. .: "
 2501 PRINT AT X+1,Y;": ' : "
 2502 PRINT AT X+2,Y;"'  ' "
 2503 RETURN 
 2600 PRINT AT X,Y;":. : "
 2601 PRINT AT X+1,Y;": '.: "
 2602 PRINT AT X+2,Y;"'  ' "
 2603 RETURN 
 2700 PRINT AT X,Y;".'''. "
 2701 PRINT AT X+1,Y;":  : "
 2702 PRINT AT X+2,Y;" '''"
 2703 RETURN 
 2800 PRINT AT X,Y;":'''. "
 2801 PRINT AT X+1,Y;":'''"
 2802 PRINT AT X+2,Y;"' "
 2803 RETURN 
 2900 PRINT AT X,Y;".'''. "
 2901 PRINT AT X+1,Y;": '.' "
 2902 PRINT AT X+2,Y;" '' ' "
 2903 RETURN 
 3000 PRINT AT X,Y;":'''. "
 3001 PRINT AT X+1,Y;":'':"
 3002 PRINT AT X+2,Y;"'  ' "
 3003 RETURN 
 3100 PRINT AT X,Y;".'''"
 3101 PRINT AT X+1,Y;" '''. "
 3102 PRINT AT X+2,Y;" '''"
 3103 RETURN 
 3200 PRINT AT X,Y;"'':'' "
 3201 PRINT AT X+1,Y+1;": "
 3202 PRINT AT X+2,Y+1;"' "
 3203 RETURN 
 3300 PRINT AT X,Y;":  : "
 3301 PRINT AT X+1,Y;":  : "
 3302 PRINT AT X+2,Y;" '''"
 3303 RETURN 
 3400 PRINT AT X,Y;":  : "
 3401 PRINT AT X+1,Y;" : :"
 3402 PRINT AT X+2,Y+1;"' "
 3403 RETURN 
 3500 PRINT AT X,Y;":  : "
 3501 PRINT AT X+1,Y;": : : "
 3502 PRINT AT X+2,Y;" ' '"
 3503 RETURN 
 3600 PRINT AT X,Y;"'. .' "
 3601 PRINT AT X+1,Y;" .'."
 3602 PRINT AT X+2,Y;"'  ' "
 3603 RETURN 
 3700 PRINT AT X,Y;"'. .' "
 3701 PRINT AT X+1,Y+1;": "
 3702 PRINT AT X+2,Y+1;"' "
 3703 RETURN 
 3800 PRINT AT X,Y;"''':' "
 3801 PRINT AT X+1,Y;" .' "
 3802 PRINT AT X+2,Y;"''''' "
 3803 RETURN 
 3810 SAVE "1010%3"
 3820 RUN 
 9999 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