This program displays an animated Christmas and New Year greeting card with scrolling graphical decorations. It uses machine code via RAND USR 16514 and a POKE to address 16418 to initialise the display environment before the main loop. Three string variables (B$, C$, D$) each hold a 64-character pattern built from block graphics representing candles or decorative motifs, and are horizontally scrolled each frame by rotating the string one character left using the slice idiom s$(2 TO LEN s$)+s$(1). The PRINT statement alternates between inverse-video and normal-video versions of “MERRY CHRISTMAS” and “HAPPY NEW YEAR” text, creating a flashing effect on each loop iteration.
Program Analysis
Program Structure
The program divides into four functional phases:
- Initialisation (lines 2–6): Sets FAST mode, calls machine code at 16514, POKEs address 16418 to zero, prints a bottom border row, then restores SLOW mode.
- String setup (lines 10–40): Builds the shared prefix
A$and constructs three display stringsB$,C$,D$each longer than 32 characters to support rotation. - Display loop (line 100): A single compound
PRINT ATstatement renders three rows of graphics and two text labels in both normal and inverse video. - Scroll update (lines 200–300): Each string is rotated left by one character and control returns to line 100.
Machine Code Usage
RAND USR 16514 at line 3 calls a machine-code routine at address 16514 in RAM. On a standard 16K or 64K TS1000/ZX81 this area sits within the system variables or early RAM; the exact function depends on what has been loaded or pre-POKEd into that location, but this pattern is a common technique to execute an initialisation stub before the BASIC program runs. The subsequent POKE 16418,0 writes to the system variable RAMTOP low byte or a related display variable to adjust memory layout or clear a flag.
String Construction and the Rotation Idiom
All three animated strings are constructed by concatenating A$ (32 spaces in inverse video acting as a left-pad buffer) with a pattern of block graphics. This makes each string 64+ characters long. The rotation at lines 200–220 uses the classic ZX81 cyclic-shift idiom:X$ = X$(2 TO LEN X$) + X$(1)
This drops the first character and appends it to the end, producing a one-character leftward scroll per frame. Printing only the first 32 characters with the slice B$( TO 32) then shows a moving window across the pattern, creating smooth horizontal animation without any array or loop overhead.
Block Graphics Usage
The three display rows use ZX81 block graphic characters to suggest a repeating decorative motif (likely stylised candles or Christmas trees):
| String | Row | Graphics used | Visual role |
|---|---|---|---|
B$ | Top | ▝▝▐, O, / | Flame / top of candle |
C$ | Middle | ▖, dashes, % | Candle body |
D$ | Bottom | ▌▌▌, ▐▐▐, \;;\;; sequences | Candle base / holder |
The \;; sequences in D$ represent character code 59 (semicolon) used as a block-fill element for the base row.
Flashing Text Technique
Line 100 prints the two greeting strings twice within the same PRINT statement: first in inverse video (%H%A%P%P%Y%… and %M%E%R%R%Y%…) and then in normal video. Because SLOW mode re-enters the display interrupt on each frame, the two renderings appear in rapid alternation across loop iterations, producing a flashing effect without any explicit IF branch or flag variable.
Key BASIC Idioms
- Compound
PRINT AT … ; AT … ; AT …in a single statement to minimise interpreter overhead per frame. - String slicing with
( TO 32)to extract a fixed-width window from a longer rotating buffer. LET B$=A$+"…"pattern to share the common 32-character prefix across all three row strings, saving re-typing and memory.GOTO 100infinite loop with no termination condition — typical for demo/greeting programs.
Content
Source Code
1 REM Y% \.'\. :%KNOT $TAB \@@RND\: TAB \'.RNDTAN
2 FAST
3 RAND USR 16514
4 POKE 16418,0
5 PRINT AT 22,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
6 SLOW
10 LET A$="% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
20 LET B$=A$+"\ '\ '\ :% % \ '\ '\ :% % \ '\ '\ :% % \ '\ '\ :% % % %/% %O % "
30 LET C$=A$+"% \ .%-%- \ .%-%- \ .%-%- \ .%-%- % "
40 LET D$=A$+"% \: \: \: % % \ :\ :\ :% % \ :\ :\ :% % \ :\ :\ :% % \;;\;;\;;\;;% "
100 PRINT AT 10,0;B$( TO 32);AT 11,0;C$( TO 32);AT 12,0;D$( TO 32);AT 4,8;"MERRY CHRISTMAS";AT 18,8;"%H%A%P%P%Y% %N%E%W% %Y%E%A%R";AT 4,8;"%M%E%R%R%Y% %C%H%R%I%S%T%M%A%S";AT 18,8;"HAPPY NEW YEAR"
200 LET B$=B$(2 TO LEN B$)+B$(1)
210 LET C$=C$(2 TO LEN C$)+C$(1)
220 LET D$=D$(2 TO LEN D$)+D$(1)
300 GOTO 100
\n9998 SAVE "SEASONS GREETING%S"
\n9999 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
