This is an interactive drawing program that lets the user move a cursor around the ZX81/TS1000 screen using keys 5, 6, 7, and 8 (left, up, down, right) and toggle between draw and erase modes with keys R and D. The program uses PLOT and UNPLOT to set and clear individual pixels, with the cursor constrained to the plotting area (X: 0–50, Y: 10–43). Mode switching is handled by storing the current mode in the string variable F$, where “R” means erase (UNPLOT before each PLOT) and “D” means draw. The SAVE command on line 500 includes an inverse-video character in the filename, which acts as an auto-run flag.
Program Analysis
Program Structure
The program is divided into logical blocks by line number ranges:
- Lines 5–30: Initialisation — title print, cursor position (
X=0,Y=10), and default mode (F$="R"). - Lines 100–110: Mode-switching input — checks for
R(erase) orD(draw). - Lines 190–230: Erase step and movement input — conditionally UNPLOTs, then reads directional keys.
- Lines 300–330: Boundary clamping — keeps cursor within the drawable area.
- Line 340: Plots the new cursor position.
- Line 400: Main loop jump back to line 100.
- Lines 500–510: SAVE and LIST utilities, not part of the running program.
Drawing Modes
The variable F$ controls whether the program is in draw or erase mode. When F$="R", line 190 executes UNPLOT X,Y before the new position is plotted at line 340, effectively erasing the previous pixel and producing a moving cursor with no trail. When F$="D", line 190 is skipped, leaving every visited pixel set — this is the actual drawing mode. The naming is slightly counter-intuitive: “R” (for “Rubber”?) erases, while “D” draws.
Input Handling
All input is polled via INKEY$ inside the main loop with no debouncing or waiting. Movement uses the classic ZX81 cursor key layout: 5=left, 6=up, 7=down, 8=right. Mode switching on lines 100 and 110 re-reads INKEY$ independently on each line, meaning the key must still be held when each line executes — a potential race condition where a quick keypress might be missed or partially registered.
Boundary Clamping
Lines 300–330 clamp X and Y to the valid plotting range before the PLOT on line 340. The Y range of 10–43 keeps the cursor out of the text area used by the title on line 5. The X range of 0–50 is well within the ZX81’s 64-pixel-wide display. Clamping is done with simple IF/LET pairs rather than MIN/MAX functions (which are not available in this BASIC).
Notable Techniques and Anomalies
- The program uses separate INKEY$ reads for mode switching (lines 100, 110) and movement (lines 200–230), meaning up to five independent key polls happen per loop iteration — potentially causing inconsistent behaviour at borderline key timings.
- In erase mode (
F$="R"), UNPLOT is applied to the current position before the move is processed, so the old pixel is cleared and then the new position is plotted, giving a single-pixel travelling cursor effect. - The default mode at startup is
F$="R"(erase/cursor), so the user must press D to begin drawing. - There is no mechanism to detect or handle
INKEY$returning an empty string differently from no input — movement simply does not occur if no key is held, which is the expected ZX81 idiom for real-time control.
Variable Summary
| Variable | Purpose |
|---|---|
X | Horizontal cursor position (0–50) |
Y | Vertical cursor position (10–43) |
F$ | Mode flag: “R” = erase/cursor, “D” = draw |
Content
Source Code
5 PRINT "%D%R%A%W%I%N%G"
10 LET X=0
20 LET Y=10
30 LET F$="R"
100 IF INKEY$="R" THEN LET F$=INKEY$
110 IF INKEY$="D" THEN LET F$=INKEY$
190 IF F$="R" THEN UNPLOT X,Y
200 IF INKEY$="5" THEN LET X=X-1
210 IF INKEY$="6" THEN LET Y=Y-1
220 IF INKEY$="7" THEN LET Y=Y+1
230 IF INKEY$="8" THEN LET X=X+1
300 IF X>50 THEN LET X=50
310 IF X<0 THEN LET X=0
320 IF Y>43 THEN LET Y=43
330 IF Y<10 THEN LET Y=10
340 PLOT X,Y
400 GOTO 100
500 SAVE "1004%4"
510 LIST
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
