ROLL OVER

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Demo

ROLL OVER is a text animation routine that creates a “rolling” color-cycling effect on a string of characters printed to the screen. The subroutine at line 9000 first copies character bitmap data from the system font (via the `ch` pointer at address 23606/23607) into the display file area (via the `gr` pointer at address 23675/23676), doubling each row of pixels by writing it twice to consecutive byte pairs. It then animates the string by cycling through PAPER/INK attribute combinations using `CHR$ (142+2*z)` and scrolling the attribute value downward through positions 0–7 in a loop of 10 repetitions. System variables at 23675/23676 (D_FILE) and 23606/23607 (CHARS) are accessed directly via PEEK to locate the display file and character set in memory.


Program Structure

The program is short, consisting of a main section (lines 5–30) and a reusable subroutine (lines 9000–9120). The main section sets screen colors, calls the subroutine twice with different strings ("ROLL OVER" and "Try Again"), then halts. The subroutine is self-contained and driven entirely by the string passed in x$.

LinesRole
5Set PAPER 6, BORDER 4
10–20Set x$ and call subroutine
30STOP
9000–9010Read system variable pointers for display file and character set
9020–9060Copy font bitmaps into display file, doubled vertically
9070–9110Animate by cycling attribute bytes and reprinting string
9120Restore D_FILE low byte, return

System Variable Access

The subroutine makes direct use of two Spectrum system variables:

  • 23675/23676 — D_FILE (display file address), read at line 9000 to locate where character cell bitmaps live in memory.
  • 23606/23607 — CHARS (character set base address), read at line 9010 to find the ROM font.

Both 16-bit values are assembled from their low and high bytes using the standard PEEK low + 256 * PEEK high idiom, storing results in gr and ch respectively.

Bitmap Copying with Vertical Doubling

Lines 9020–9060 iterate over every character in x$. For each character, its ASCII code is obtained with CODE x$(z+1). The eight pixel rows of that character’s font data are read from ch + (a*8) + n. Each row byte v is written to two consecutive positions in the display file: once at gr + (16*z) + n and again at gr + (16*z) + 8 + n. This doubles each character row, effectively stretching each glyph to occupy 16 bytes instead of the usual 8 — a simple vertical scaling technique using only PEEK and POKE.

Color Animation

The animation loop (lines 9070–9110) runs 10 repetitions (r). Within each repetition, the low byte of D_FILE is temporarily modified via POKE 23675, n+88 as n counts down from 7 to 0, shifting which part of the display file is addressed. Simultaneously, line 9100 rebuilds x$ by replacing each character with CHR$ (142 + 2*z), generating color attribute control characters that vary per character position. The string is then printed at a fixed screen position with PRINT AT 10,10;x$, causing each character to display with a different, cycling PAPER/INK combination.

Notable Techniques

  • D_FILE manipulation: Temporarily altering the low byte of the display file pointer (POKE 23675, n+88) redirects where the system reads display data, creating a scrolling or rolling visual without moving any pixel data.
  • Attribute color cycling: Using CHR$ (142 + 2*z) produces embedded color-change escape sequences within a string, allowing per-character attribute control inside a single PRINT statement.
  • Subroutine reuse: The same subroutine handles strings of any length because all loops are bounded by LEN x$.

Potential Anomalies

Line 9080 sets POKE 23675, 88+8 (= 96) immediately before the inner loop resets it in steps from 95 down to 88. This initial POKE may be a preparatory state or a minor redundancy, since the inner loop at line 9090 immediately overwrites it. Additionally, line 9100 permanently overwrites the contents of x$ with control characters on each pass through the outer loop, meaning the original string text is destroyed after the first animation frame. For the demo’s purposes this is harmless since the subroutine returns after the animation, but callers should be aware that x$ is not preserved.

Image Gallery

Source Code

    5 PAPER 6: BORDER 4
   10 LET x$="ROLL OVER": GO SUB 9000
   20 LET x$="Try Again": GO SUB 9000
   30 STOP 
 9000 LET gr=PEEK 23675+256*PEEK 23676
 9010 LET ch=PEEK 23606+256*PEEK 23607
 9020 FOR z=0 TO (LEN x$-1): LET a=CODE x$(z+1)
 9030 FOR n=0 TO 7: LET v=PEEK (ch+(a*8)+n)
 9040 POKE (gr+(16*z)+n),v
 9050 POKE (gr+(16*z)+8+n),v
 9060 NEXT n: NEXT z
 9070 FOR r=1 TO 10
 9080 POKE 23675,88+8
 9090 FOR n=7 TO 0 STEP -1: POKE 23675,(n+88)
 9100 FOR z=1 TO LEN x$: LET x$(z)=CHR$ (142+2*z): NEXT z
 9110 PRINT AT 10,10;x$: NEXT n: NEXT r
 9120 POKE 23675,88: RETURN 

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