This program displays a scrolling text animation by decoding a compact run-length encoded string stored across twelve DATA lines. Characters are read from the DATA strings, decoded by adding 63 to their ASCII code to recover display characters, and packed five characters at a time into a 130×5 string array B$. The letters “R” and “Q” serve as run-length control codes: “Q” advances the position counter by one (inserting a space or skip), while “R” advances it by four, efficiently compressing repeated blank regions. The decoded content is then displayed five rows at a time at screen position (7,14), cycling through the array in a continuous loop controlled by INKEY$ and PAUSE 20.
Program Analysis
Program Structure
The program has two distinct phases: a data initialization phase (lines 10–80) and a display loop (lines 90–110), followed by twelve DATA statements (lines 1000–1110). The initialization phase reads twelve strings from DATA, decodes each character, and fills the array B$. The display loop then scrolls through B$ five rows at a time in a continuous cycle.
Array Layout
B$ is dimensioned as DIM B$(130,5), giving 130 rows of 5-character strings. The variable C is a flat linear counter; for each character position, row index I = INT(C/5)+1 and column index J = C - I*5 + 6 are computed. This maps the sequential counter into the two-dimensional array. The column formula J = C - I*5 + 6 is equivalent to (C MOD 5) + 1, since C MOD 5 = C - INT(C/5)*5 and the offset of 6 versus 5 accounts for the 1-based indexing.
Run-Length Encoding Scheme
The DATA strings use a simple run-length encoding with two control characters:
"Q"— skip: advancesCby 1 without writing a character (line 60, then falls through toC=C+1at line 80, net +1 advance but no write)."R"— run: advancesCby 4 at line 50, then by 1 more at line 80, for a net +5 skip, bypassing five cell positions.
Any other character is decoded by adding 63 to its character code (line 70: CHR$ (CODE A$(Y)+63)), which shifts the printable ASCII range into the ZX81’s character set, and stored into B$(I,J). The counter C is always incremented by 1 at line 80 after any branch, so “Q” produces a net +1 and a blank cell, and “R” produces a net +5 blank cells.
Display Loop
Lines 90–110 iterate I from 1 to 126 in steps of 5, printing five consecutive rows of B$ at screen rows 7–11, column 14. The INKEY$="" check at line 100 pauses for 20/50ths of a second only when no key is pressed, allowing a key press to accelerate the scroll. After reaching row 126, GO TO 90 restarts from the beginning, creating a continuous loop.
Notable Techniques
- The character encoding shift of +63 is a compact way to remap a subset of printable ASCII characters into displayable ZX81 characters, avoiding the need to store the target characters directly in the DATA strings.
- The “R” skip of 5 positions aligns naturally with the 5-character row width, allowing entire blank rows to be skipped in a single encoded character.
- Using
INKEY$withPAUSE 20rather than a fixed delay allows interactive speed control without a dedicated key-handling loop. - The flat counter
Cwith inline index arithmetic avoids nested loop variables during data loading, keeping the DATA reading loop straightforward.
Potential Anomalies
The column index formula LET J=C-I*5+6 at line 40 uses I which was just computed as INT(C/5)+1, so I*5 = INT(C/5)*5 + 5. This means J = C - INT(C/5)*5 - 5 + 6 = (C MOD 5) + 1, which is correct for 1-based indexing into a 5-character string. However, when A$(Y)="R", C is incremented by 4 before reaching line 80’s increment, meaning C ends up 5 higher. If this happens mid-row (i.e., C MOD 5 ≠ 0), the skip may straddle two rows rather than skipping exactly one full row, potentially misaligning subsequent characters. This is an inherent risk of run-length encoding without row-boundary alignment guarantees.
Data Summary
| Lines | Role |
|---|---|
10 | Initialize array B$ (130×5) and counter C |
20–80 | Data loading loop: read 12 strings, decode RLE, fill B$ |
90–110 | Display loop: scroll 5 rows at a time, repeat continuously |
1000–1110 | Twelve RLE-encoded DATA strings containing the message content |
Content
Source Code
10 DIM B$(130,5): LET C=0
20 FOR X=0 TO 11: READ A$
30 FOR Y=1 TO LEN A$
40 LET I=INT (C/5)+1: LET J=C-I*5+6
50 IF A$(Y)="R" THEN LET C=C+4: GO TO 80
60 IF A$(Y)="Q" THEN GO TO 80
70 LET B$(I,J)=CHR$ (CODE A$(Y)+63)
80 LET C=C+1: NEXT Y: NEXT X
90 FOR I=1 TO 126 STEP 5
100 IF INKEY$="" THEN PAUSE 20
110 FOR J=0 TO 4: PRINT AT 7+J,14;B$(I+J): NEXT J: NEXT I: GO TO 90
1000 DATA "QFAKQQFAKQQQPQQRRQGQJQQFQKQQQPQQ"
1010 DATA "RRBIQECQFQKQQQPQQRRMQQQMQGQJQQQP"
1020 DATA "QQRRRDGQJDQQPQQRRRMMQMMQQPQQRRRR"
1030 DATA "DDPDDRRRRMMPMMRRRREMPMICQQQBRRRQ"
1040 DATA "MPMQJQQQGRRRQEPIQECQBICQQQBRRQQP"
1050 DATA "QQQJQGQJQQQGRRQQPQQQJQGQFQQQKRRQ"
1060 DATA "QPQQQJQGQQKQFQRRQQPQQQFQKQQFQKQR"
1070 DATA "RQMPMQQGQJQRRRQLPHAQCQBQRRQIQEQQ"
1080 DATA "LPHQRRRQOQNQQCPBARRRQPQPQAAPAARR"
1090 DATA "REHQLIQQPQQRRRBHQLCQQPQQRRQMQMQQ"
1100 DATA "FQKQAAPAARRQGQJQQFQKQQQPQQRRQFQK"
1110 DATA "QQFQKQQQPQQRRQEDIQQFQKQQQPQQRR"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
