Spectrum Draw

Developer(s): Floyd Chrysler
Date: 198x
Type: Program
Platform(s): TS 2068

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:

AddressRole
30017Redraw/refresh the screen or reset display state; called after most user-visible operations.
31967Main interactive loop entry — reads joystick/keyboard and dispatches to BASIC subroutines via GO SUB USR.
31526Execute 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.
31176Render 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:

AddressValuePurpose
236937System variable ATTR P — permanent attribute (white paper, white ink)
236940System variable MASK P
236970System variable P FLAG
32578128Machine code variable: current X position (low byte)
3257988Machine code variable: current Y position
325821Machine code flag (likely draw colour/mode)
325831Machine code flag
236810System 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.

Content

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.

Related Products

Related Articles

Related Content

Image Gallery

Spectrum Draw

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 

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

Scroll to Top