This program implements a scrolling word-display effect that renders user-input text one word at a time using pixel-level character plotting. It prompts the user for a message, then extracts words sequentially via a subroutine at line 1000, rendering each word by PEEKing the ZX81 character ROM at address 7680 to read 8×8 font bitmaps and plotting individual pixels. After displaying each word, the screen scrolls up by G lines (normally 4, but 21 at the end of the message to clear the screen), then loops back to the start of the message. The program handles inverse-video characters by subtracting 128 from their character code before the ROM lookup, storing the stripped character in M$ (though M$ is set but never used to adjust the PLOT call, which is a bug).
Program Analysis
Program Structure
The program is divided into a main loop and two subroutines. Initialisation sets the word-start pointer S=1 and the scroll amount G=4. After prompting for input and appending two trailing spaces to B$ (line 80), the program enters a perpetual loop: call the word-extraction subroutine, scroll the screen, plot the word pixel by pixel, then repeat.
- Lines 10–90 – Initialisation and user prompt.
- Lines 130–360 – Main display loop: extract word, scroll, plot pixels, repeat.
- Lines 1000–1070 – Word extraction subroutine: scans
B$from positionSto the next space, returning the word inA$. - Lines 2000–2030 – End-of-message subroutine: resets
Sand adjusts scroll count when the last word is reached. - Line 9998–9999 – SAVE with auto-run flag, then
RUN.
Character ROM Access
The pixel rendering (lines 200–350) reads font data directly from ROM. The ZX81 character set begins at address 7680, with each character occupying 8 consecutive bytes (one per pixel row). Line 260 computes the address as 7680 + C*8 + L, where C is the character code and L is the row (0–7). Each byte is then bit-shifted by successive halving of V (starting at 128) to isolate individual pixels, which are plotted at PLOT 8*(K-1)+J, 10-L.
Word Extraction (Subroutine 1000)
The subroutine scans B$ from the current word pointer S until it finds a space character, storing the word slice in A$ and advancing S past the delimiter. The two trailing spaces appended at line 80 ensure the final word is always followed by a space, preventing an out-of-bounds substring error.
End-of-Message Handling (Subroutine 2000)
Called once per pixel plot (line 305), this subroutine checks whether the current word index N has reached the end of B$. When it has, it resets S=1 (restarting from the first word on the next cycle) and sets G=21 to scroll the display clear before the loop begins again. For all other words, G is kept at 4.
Notable Techniques
- Bitmap font decoding: The successive-halving loop (
V=128→V=V/2) is a common ZX81 idiom for extracting bits without using AND or integer arithmetic beyond subtraction. - Trailing-space sentinel: Appending
" "toB$at line 80 is a neat boundary-condition fix for the word-scanner loop. - Dynamic scroll depth: Varying
Gbetween 4 and 21 allows normal inter-word scrolling while still clearing the screen between complete message cycles. - Inverse-video stripping: Line 220 detects codes ≥128 (inverse characters) and subtracts 128 to get the normal code for the ROM lookup.
Bugs and Anomalies
| Location | Issue |
|---|---|
| Lines 230–240 | M$ is assigned the base character at line 230 and C is set to 0, but M$ is never used again. Setting C=0 means that any inverse character in the input is rendered as the @ character (code 0) rather than its correct inverse form — the intended logic to use M$‘s code is missing. |
| Line 305 | GOSUB 2000 is called inside three nested FOR loops (over characters, rows, and columns), so the end-of-message check fires up to 64 times per character. This is harmless since the assignments are idempotent, but it is inefficient. |
| Line 1010 | If the input message contains no spaces at all, the inner loop at line 1020 will run past the end of B$ (the two appended spaces provide a fallback, so this is only a concern if B$ overflows available string space). |
Content
Source Code
10 LET S=1
20 LET G=4
60 PRINT AT 10,0;"TYPE IN A MESSAGE."
70 INPUT B$
80 LET B$=B$+" "
90 CLS
130 GOSUB 1000
170 FOR I=1 TO G
180 SCROLL
190 NEXT I
200 FOR K=1 TO LEN A$
210 LET C=CODE A$(K)
220 IF C<128 THEN GOTO 250
230 LET M$=CHR$ (C-128)
240 LET C=0
250 FOR L=0 TO 7
260 LET P=PEEK (7680+C*8+L)
270 LET V=128
280 FOR J=0 TO 7
290 IF P<V THEN GOTO 320
300 PLOT 8*(K-1)+J,10-L
305 GOSUB 2000
310 LET P=P-V
320 LET V=V/2
330 NEXT J
340 NEXT L
350 NEXT K
360 GOTO 130
1000 FOR N=S TO LEN B$
1010 IF B$(N)=" " THEN GOTO 1050
1020 NEXT N
1050 LET A$=B$(S TO N-1)
1060 LET S=N+1
1070 RETURN
2000 IF N<LEN B$-1 THEN LET G=4
2010 IF N>=LEN B$-1 THEN LET S=1
2020 IF N>=LEN B$-1 THEN LET G=21
2030 RETURN
9998 SAVE "SUPERSCROL%L"
9999 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
