--- title: "Spectrum Draw" id: 64595 type: "computer_media" slug: "spectrum-draw" url: "http://localhost/computer_media/spectrum-draw/" markdown_url: "http://localhost/computer_media/spectrum-draw.md" published_at: "2026-03-03T01:25:16+00:00" modified_at: "2026-03-30T21:45:28+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2023/06/5-SpecDraw.png" excerpt: "A machine code art package from Your Computer gets a TS2068 conversion—with BASIC-driven parametric circles, screen save/load, and text overlay routines." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Floyd Chrysler" slug: "floyd-chrysler" taxonomy: "indiv" url: "http://localhost/indiv/floyd-chrysler/" genre: - name: "Graphics" slug: "graphics" taxonomy: "genre" url: "http://localhost/type/graphics/" media_contents: - id: 64513 title: "CATS Library Tape 2" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-2/" media_type: "Program" programmers: - name: "Floyd Chrysler" slug: "floyd-chrysler" taxonomy: "indiv" url: "http://localhost/indiv/floyd-chrysler/" download_url: "https://archive.org/download/timex-sinclair-software-archive/RandomFan%20%28198x%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2023/06/5-SpecDraw.png" media_type_tags: "Graphics" --- This program is a BASIC loader and menu shell for a machine code drawing application called “DRAW,” converted from a Spectrum original (published in Your Computer, June 1984) to the Timex/Sinclair 2068. The BASIC sets up system variables via POKE, loads the machine code block at address 30000 (2610 bytes), and enters a tight loop at line 40 that repeatedly calls a machine code routine at USR 31967 to handle user input and drawing. Subroutines at lines 1000–1210 handle saving/loading screen data and overlaying text, while the circle-drawing subroutine at lines 3000–3130 computes a parametric circle in BASIC using SIN/COS, calling USR 31526 to execute each DRAW step in machine code. Line 9000 provides a SAVE routine to re-save both the BASIC loader and the machine code block. *** ## Program Structure The program is organised as a thin BASIC shell around a substantial machine code block. Execution flows as follows: 1. **Lines 10–30:** Initialisation — set border/paper/ink via POKEs to system variables, `CLEAR 29999` to protect the machine code area, then `LOAD "DRAW" CODE` to bring in 2610 bytes at address 30000. 2. **Line 30:**`RANDOMIZE USR 30017` — one-shot machine code initialisation entry point. 3. **Line 40:**`GO SUB USR 31967: GO TO 40` — the main event loop; the machine code routine handles input and calls back into BASIC subroutines as needed. 4. **Lines 1000–1210:** BASIC subroutines for saving a screenshot (`SAVE … SCREEN$`), loading a screenshot, and printing text onto the drawing. 5. **Lines 3000–3130:** A parametric circle-drawing subroutine, selectable with or without recentring (flag `F`). 6. **Line 9000:** Development utility to re-save both the BASIC program and the machine code block. ## Machine Code Interface Three distinct machine code entry points are visible in the BASIC: | Address | Role | | --- | --- | | `30017` | Redraw/refresh the screen or reset display state; called after most user-visible operations. | | `31967` | Main interactive loop entry — reads joystick/keyboard and dispatches to BASIC subroutines via `GO SUB USR`. | | `31526` | Execute a single DRAW step using delta coordinates held in BASIC variables `X`, `IX`, `Y`, `IY`; the `REM` comments on lines 3100 and 3120 document the intended arguments. | | `31176` | Render the text string held in `A$` onto the screen. | The pattern `RANDOMIZE USR addr` is the standard idiom for calling machine code while discarding any return value; the Z80 routine returns 0 in BC, which `RANDOMIZE` accepts without error. The `GO SUB USR 31967` idiom (line 40) is less common: the machine code routine must itself execute a Z80 `RET` that maps to a BASIC `RETURN`, causing the BASIC interpreter to treat execution as if a GOSUB had returned, then `GO TO 40` re-enters it. This gives the machine code full control while still allowing it to invoke BASIC subroutines. ## Memory Map and POKEs Lines 10 and 20 configure both Spectrum system variables and custom machine code parameters: | Address | Value | Purpose | | --- | --- | --- | | `23693` | 7 | System variable `ATTR P` — permanent attribute (white paper, white ink) | | `23694` | 0 | System variable `MASK P` | | `23697` | 0 | System variable `P FLAG` | | `32578` | 128 | Machine code variable: current X position (low byte) | | `32579` | 88 | Machine code variable: current Y position | | `32582` | 1 | Machine code flag (likely draw colour/mode) | | `32583` | 1 | Machine code flag | | `23681` | 0 | System variable `COORDS` X (reset graphics cursor) | ## Parametric Circle Subroutine (Lines 3000–3130) The circle routine demonstrates an interesting BASIC/machine-code hybrid approach. It computes the circle radius from two stored points (current position and an “input” point read from addresses `32578–32581`), then steps around the circumference using `COS` and `SIN`: - `R = SQR((CX-IX)²+(CY-IY)²)` — Euclidean radius in screen pixels. - Step size `S` is chosen adaptively: `2*INT(INT(PI*SQR(R)+0.5)/2)+2` — this rounds up to the nearest even integer, ensuring the loop closes cleanly. It is clamped to 252 to avoid excessively long loops for large circles. - Each vertex is passed to the machine code DRAW routine at USR 31526 as a delta from the previous point (`X-IX`, `Y-IY`), matching the Spectrum’s native `DRAW dx,dy` semantics. - Lines 3000 and 3010 set flag `F`: when `F=1` (entered via line 3010), the centre is moved to the previous input point before drawing, enabling concentric or chained circles. ## Text Overlay (Lines 1200–1210) Line 1200 uses an `INPUT AT 0,0; PAPER 6; INK 0;` prompt that dynamically calculates the maximum number of characters that fit on the remaining canvas width: `INT((256 - PEEK 32578)/8 / PEEK 23728)`. Here `PEEK 32578` gives the current X pixel position and `PEEK 23728` is the system variable `DF SZ` (lower screen size). The trailing `PRINT ;` after the INPUT anchors the cursor, and then USR 31176 renders `A$` using the machine code text renderer. The `REM A$` at the end of line 1200 is a documentation comment; in Sinclair BASIC a `REM` following a colon is never executed, so it serves purely as an in-line note to indicate that `A$` is the operative variable. ## Save/Load Subroutines Lines 1000 and 1100 validate the filename (1–10 characters) before performing `SAVE/LOAD … SCREEN$` operations. The validation loop `IF NOT LEN A$ OR LEN A$>10 THEN GO TO 1000` re-prompts on empty or over-length names. After each save or load, `RANDOMIZE USR 30017` is called to refresh the display from the machine code side. ## Development Save Line Line 9000 re-saves the full package: `SAVE "specdraw" LINE 1` stores the BASIC with auto-run at line 1, followed by `SAVE "DRAW" CODE 30000,2610` to dump exactly the 2610-byte machine code block. The subsequent `STOP` prevents accidental fall-through. ## Source Code ``` 1 REM spectrum draw ---- from YOUR COMPUTER June 1984 converted to T/S2068 by F. Chrysler. 10 POKE 23693,7: POKE 23694,0: POKE 23697,0: BORDER 0: CLEAR 29999: LOAD "DRAW"CODE : CLS 20 POKE 32583,1: POKE 32582,1: POKE 23681,0: POKE 32578,128: POKE 32579,88 30 RANDOMIZE USR 30017 40 GO SUB USR 31967: GO TO 40 1000 INPUT "Name ? "; LINE A$: IF NOT LEN A$ OR LEN A$>10 THEN GO TO 1000 1010 SAVE A$ SCREEN$ : RANDOMIZE USR 30017: RETURN 1100 INPUT "Name ? "; LINE A$: LOAD A$SCREEN$ : RANDOMIZE USR 30017: RETURN 1200 RANDOMIZE USR 30017: INPUT AT 0,0; PAPER 6; INK 0;"Text (max. ";INT ((256-PEEK 32578)/8/PEEK 23728);")",, LINE A$: PRINT ;: RANDOMIZE USR 31176: REM A$ 1210 RANDOMIZE USR 30017: RETURN 3000 LET F=0: GO TO 3020 3010 LET F=1 3020 LET CX=PEEK 32578: LET CY=PEEK 32579: LET IX=PEEK 32580: LET IY=PEEK 32581: LET R=SQR ((CX-IX)*(CX-IX)+(CY-IY)*(CY-IY)) 3030 IF F THEN LET CX=IX: LET CY=IY 3050 LET IX=CX+R: LET IY=CY: POKE 32584,IX-256*INT (IX/255): POKE 32585,128+INT (IX/255): POKE 32586,IY: POKE 32587,128 3060 LET S=2*INT (INT (PI*SQR R+.5)/2)+2: IF S>252 THEN LET S=252 3070 FOR N=0 TO 2*PI STEP PI/S 3080 LET X=INT (.5+CX+R*COS N) 3090 LET Y=INT (.5+CY+R*SIN N) 3100 RANDOMIZE USR 31526: REM X-IX,Y-IY 3110 LET IY=Y: LET IX=X: NEXT N 3120 RANDOMIZE USR 31526: REM CX+R-IX,CY-IY 3130 RANDOMIZE USR 30017: RETURN 9000 SAVE "specdraw" LINE 1: SAVE "DRAW"CODE 30000,2610: STOP ```