This program is a freehand drawing utility that allows the user to move a cursor around the high-resolution graphics screen using the arrow keys (5, 6, 7, 8), toggling between a draw mode and a move/erase mode. It supports text placement at an arbitrary screen position, screen save and load via SCREEN$ commands, and hardcopy output via the COPY statement to a compatible printer. The program uses OVER 1 plotting to draw and OVER 0 to erase, exploiting the XOR-like behavior of the OVER attribute for pixel toggling. Originally written by Harry W. Johnson and Gary L. Swartz in 1984, it was subsequently revised for the TS2068 by John Marion.
Program Analysis
Program Structure
The program is organized into several distinct functional blocks:
- Lines 10–190: Main initialization and drawing loop. Sets up the screen, initializes cursor position at (110, 80), and continuously polls
INKEY$to move the cursor and dispatch to subroutines. - Lines 200–450: Help/intro subroutine displaying key bindings across two screenfuls, waiting for a keypress between pages using
PAUSE 4E4. - Lines 500–640: Text placement mode — moves a
>cursor character around the text grid, then accepts anINPUTstring and prints it at the chosen position. - Lines 700–730: Screen save routine using
SAVE A$SCREEN$. - Lines 750–770: Screen load routine using
LOAD A$SCREEN$. - Lines 800–810: Program self-save with
SAVE "PLOTTER" LINE 10followed byRUN(never reached in normal execution).
Drawing Mechanism
The draw/move toggle is controlled by the variable MODE. In draw mode (MODE=1, lines 160), the program executes OVER 1: PLOT X,Y: OVER 0: PLOT X,Y. The first PLOT with OVER 1 XORs the pixel on, and the immediate second PLOT with OVER 0 sets it unconditionally — the net result is that the pixel is always set, leaving a trail. In move/erase mode (MODE=0, lines 180), the sequence is reversed: OVER 0: PLOT X,Y: OVER 1: PLOT X,Y, which sets then XORs, toggling the pixel off and allowing the cursor to move without drawing.
This double-plot idiom is a well-known Spectrum technique for cursor visibility: the pixel under the cursor is always visible to the user regardless of the background, though here it is repurposed for draw/erase switching.
Key Bindings
| Key | Action |
|---|---|
| 5 / 8 | Move cursor left / right (X axis) |
| 6 / 7 | Move cursor down / up (Y axis) |
| D | Enter draw mode |
| M | Enter move/erase mode |
| I | Enter text placement mode |
| Z | COPY screen to printer |
| V | Clear screen (CLS) |
| S | Save screen to tape |
| L | Load screen from tape |
| Q | Quit to line 1000 (non-existent — exits to BASIC) |
Movement and Boundary Clamping
Cursor movement is handled by evaluating boolean expressions as integers: LET X=X+(INKEY$="8")-(INKEY$="5") adds 1 or subtracts 1 in a single statement, a standard Sinclair BASIC idiom. Boundary checks at lines 60–90 clamp Y to 0–175 and X to 0–255, matching the Spectrum/TS2068 high-resolution pixel grid of 256×176. Note the Y upper bound of 175 rather than 176, leaving one pixel row unreachable at the top.
Text Placement Mode (Lines 500–640)
When the user presses I, the program switches to a character-cell cursor mode. A > marker is printed at the current text row (L) and column (C), and a short delay loop (FOR V=1 TO 10) provides a simple blink effect before erasing it with a space. Navigation uses keys 5/6/7/8 mapped to column/row movement. When P is pressed, an INPUT prompt collects a string H$ which is then printed at that position. This lets the user annotate their drawing with arbitrary text.
Notable Techniques and Anomalies
POKE 23658,8at line 10 sets the system variableFLAGS2to enable caps lock, ensuring key comparisons against uppercase letters work reliably without the user needing to engage caps lock manually.PAUSE 4E4(40,000 frames ≈ 27 minutes) in the help pages is effectively a “wait for any key” idiom on this platform, since any keypress interruptsPAUSE.- The main loop polls
INKEY$independently on nearly every line (40 through 145), meaning a key held during movement could simultaneously trigger a mode switch or command dispatch — a minor input-handling weakness. GO TO 1000at line 135 (the Q/quit action) targets a non-existent line, which causes the program to terminate and return to the BASIC prompt — a deliberate exit technique.- The title screen references “2968” (line 250) where “2068” (TS2068) is clearly intended — this is a typo in the original listing.
- Lines 800–810 provide a self-save block that is never reached during normal operation but allows the developer to save the program by manually running from line 800.
Content
Image Gallery
Source Code
10 POKE 23658,8: GO SUB 200
20 LET X=110: LET Y=80
30 LET MODE=1
40 LET X=X+(INKEY$="8")-(INKEY$="5")
50 LET Y=Y+(INKEY$="7")-(INKEY$="6")
60 IF Y>175 THEN LET Y=175
70 IF Y<0 THEN LET Y=0
80 IF X>255 THEN LET X=255
90 IF X<0 THEN LET X=0
100 IF INKEY$="M" THEN LET MODE=0
110 IF INKEY$="D" THEN LET MODE=1
120 IF INKEY$="Z" THEN COPY
125 IF INKEY$="V" THEN CLS
130 IF INKEY$="I" THEN GO TO 500
135 IF INKEY$="Q" THEN GO TO 1000
140 IF INKEY$="S" THEN GO TO 700
145 IF INKEY$="L" THEN GO TO 750
150 IF MODE=0 THEN GO TO 180
160 OVER 1: PLOT X,Y: OVER 0: PLOT X,Y
170 GO TO 40
180 OVER 0: PLOT X,Y: OVER 1: PLOT X,Y
190 GO TO 40
200 CLS
210 PRINT AT 1,10;"*PLOTTER*"
220 PRINT ,," BY HARRY W. JOHNSON "
230 PRINT ,," AND GARY L. SWARTZ 1984 "
240 PRINT ,," "
250 PRINT ,,"REVISED FOR 2968 BY JOHN MARION "
260 PRINT ,,"KEY ""M"" TO MOVE WITH OUT"
270 PRINT "PLOTTING OR TO ERASE."
280 PRINT ,,"KEY ""D"" TO DRAW."
290 PRINT ,, "KEY ""Z"" TO COPY TO 2040 PRINTER."
300 PRINT ,,"MOVE USING THE ARROW KEYS."
310 PRINT ,," PRESS ANY KEY TO CONTINUE "
320 PAUSE 4E4
330 CLS
340 PRINT AT 1,10;"*PLOTTER*"
350 PRINT ,,"KEY ""I"" TO ENTER TEXT."
360 PRINT "POSITION CURSOR THEN KEY ""P"""
370 PRINT "ENTER YOUR TEXT, IT WILL APPEAR"
380 PRINT "AT CURSOR POINT."
390 PRINT ,,"KEY ""S"" TO SAVE SCREEN"
400 PRINT ,,"KEY ""L"" TO LOAD SCREEN"
405 PRINT ,,"KEY ""V"" TO CLEAR SCREEN"
410 PRINT ,,"KEY ""Q"" TO QUIT PROGRAM"
420 PRINT ,," PRESS ANY KEY TO CONTINUE "
430 PAUSE 4E4
440 CLS
450 RETURN
500 OVER 0: LET L=21: LET C=0
510 IF L>21 THEN LET L=21
520 IF L<0 THEN LET L=0
530 IF C>31 THEN LET C=31
540 IF C<0 THEN LET C=0
550 PRINT AT L,C;">"
555 FOR V=1 TO 10: NEXT V
560 PRINT AT L,C;" "
570 LET L=L+(INKEY$="6")-(INKEY$="7")
580 LET C=C+(INKEY$="8")-(INKEY$="5")
590 IF INKEY$="P" THEN GO TO 610
600 GO TO 510
610 PRINT AT L,C;">"
620 INPUT H$
630 PRINT AT L,C;" ";H$
640 GO TO 40
700 INPUT "SAVE NAME";A$
710 IF A$="" THEN GO TO 40
720 SAVE A$SCREEN$
730 GO TO 40
750 INPUT "LOAD NAME";A$
760 LOAD A$SCREEN$
770 GO TO 40
800 SAVE "PLOTTER" LINE 10
810 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.