This program displays an animated Christmas card greeting with a decorated tree and festive message, then plays three carol melodies in sequence using the BEEP command before looping. The display uses FLASH and alternating INK/PAPER colors to create a bordered announcement box, while PLOT and DRAW commands construct a filled triangle representing a Christmas tree with a star. Two UDGs are defined at line 9000 — UDG “a” (a filled circle, 60,126,255…) and UDG “b” (a hollow square/frame, 255,129,129…) — which are used as decorative ornaments scattered across the tree with randomised positions and colors. The music section at lines 110–140 reads DATA blocks for three separate tunes (“We Wish You a Merry Christmas,” “O Christmas Tree,” and another carol).
Program Analysis
Program Structure
The program is organised into distinct functional phases:
- Initialisation (lines 1–2): A
RESTOREandGO SUB 9000define the two UDG characters before any display occurs. - Header box (lines 3–12): A flashing border box is drawn using
PRINT ATwith▞block graphics, enclosing the “MERRY CHRISTMAS / FROM THE DAWSONS” message. - Tree construction (lines 15–30): A filled triangle is built with
PLOT/DRAWloops and finished with a trunk rectangle. - Ornament scatter (lines 40–100): UDG characters are placed at randomised screen positions with randomised ink colours and occasional FLASH.
- Music loop (lines 110–150): Three DATA blocks of note-duration pairs are played via
BEEP, withPAUSEgaps between tunes, looping forever viaGO TO 100. - UDG definition subroutine (lines 9000–9510): Reads eight bytes each for UDGs “a” and “b” into their respective memory locations.
UDG Definition
Line 9000 uses a compact loop: FOR i=USR "a" TO USR "b"+7 to iterate over all 16 bytes covering both UDGs in a single pass, reading from the DATA at line 9500/9510. UDG “a” (bytes 60,126,255,255,255,255,126,60) defines a filled oval/circle shape used as a bauble. UDG “b” (bytes 255,129,129,129,129,129,129,255) defines a hollow square frame. The subroutine uses RESTORE 9000 to position the DATA pointer correctly before reading.
Tree Drawing Technique
The Christmas tree is drawn at lines 20–30 using a FOR loop with a STEP of 0.5, exploiting the Spectrum’s floating-point loop counter to achieve finer horizontal density. Each iteration draws two horizontal lines symmetrically from a central spine, creating a filled triangular silhouette. Lines 25 and 30 add a star at the apex using DRAW INK 9 and a rectangular trunk drawn with a second loop.
Music DATA Format
The three carol DATA blocks use paired values (duration, note) passed directly to BEEP. Each block’s duration values are divided by a different constant to control tempo:
| Lines | DATA start | Note count | Divisor | Effect |
|---|---|---|---|---|
| 110 | 800 | 30 pairs | ÷2 | Moderate tempo |
| 120 | 900 | 61 pairs | ÷2 | Moderate tempo |
| 130 | 1000 | 57 pairs | ÷3 | Faster |
| 140 | 1010 | 96 pairs | ÷5 | Fastest |
After the four tunes, PAUSE 120 provides a gap and GO TO 100 at line 150 returns to the ornament-scatter section rather than line 110, meaning the ornaments are re-randomised on each loop but the screen background is not cleared — baubles accumulate over iterations.
Notable BASIC Idioms
RND*4+8style expressions produce random screen positions within constrained column ranges for each ornament type, distributing them across the tree area without explicit collision detection.FLASH RND*1at line 90 exploits the fact thatRNDreturns a value in [0,1) — values ≥0.5 round to 1 (FLASH on) and values <0.5 round to 0 (FLASH off), giving a 50% random flash probability.- The inner loop at lines 90–100 prints eight instances of UDG “b” per pass with randomised positions and colours, increasing ornament density on repeated loops.
INK 9(transparent ink) is used in several places to allow background paper colours to show through, and line 9999 setsINK 9as a trailing default.
Anomalies and Notes
- Line 9999 contains a bare
INK 9statement with no line flow leading to it from normal execution; it acts as a dead statement and is never reached during normal program operation. - Line 8999 is a
STOPthat prevents the interpreter from falling through from the music data into the subroutine at line 9000 if ever reached, acting as a guard. - The scripture quote at line 27 (“Unto you there has been born a Savior”) is positioned over the tree graphic area, overlapping the PLOT/DRAW content since no
CLSis issued between the tree drawing and text printing phases. - The loop variable
i(lowercase) andI(uppercase) are used interchangeably in different sections; on the Spectrum, these are treated as the same variable, which could cause loop counter interference between the ornament loops and the music loops if not properly managed byNEXTmatching.
Content
Source Code
1 REM SAVE *"XMASCARD" LINE 1
2 RESTORE : GO SUB 9000
3 BORDER 2: PAPER 1: CLS : RANDOMIZE
5 PRINT INK 2; PAPER 4; FLASH 1;AT 2,14;"▞▞▞▞▞▞▞▞▞▞▞▞▞▞▞▞▞"
6 FOR i=3 TO 5: PRINT INK 2; PAPER 4; FLASH 1;AT i,14;"▞";AT i,30;"▞": NEXT i
10 PRINT AT 3,15; INK 9;"MERRY CHRISTMAS"
11 PRINT AT 4,15; INK 9;" FROM THE";AT 5,20;"DAWSONS"
12 PRINT INK 2; PAPER 4; FLASH 1;AT 6,14;"▞▞▞▞▞▞▞▞▞▞▞▞▞▞▞▞▞"
15 INK 4
20 FOR I=16 TO 80 STEP .5: PLOT I,2*I: DRAW INK 4;(80-I),0: PLOT 80,I*2: DRAW INK 4;(80-I),0: NEXT I
25 PLOT INK 4;80,160: DRAW INK 9;0,10: PLOT INK 6;77,165: DRAW INK 9;6,0
27 PRINT INK 9;AT 14,17;"Unto you";AT 16,18;"there has been";AT 18,19;"born a Savior"
30 FOR i=16 TO 31: PLOT INK 9;70,i: DRAW INK 9;20,0: NEXT i
40 PRINT AT 15,RND*4+8; PAPER 4; INK RND*4;"\a"
50 PRINT AT 10,RND*4+7; PAPER 4; INK RND*4;"\a"
60 PRINT AT 16,RND*13+3; PAPER 7; INK RND*4;"\a"
70 PRINT AT 14,RND*2+9; PAPER 4; INK RND*4;"\a"
80 PRINT AT 17,RND*7+6; PAPER 4; INK RND*4;"\a"
90 FOR i=1 TO 8: PRINT AT 19,RND*13+3; INK RND*7; FLASH RND*1;"\b": INK 9
100 NEXT i
110 RESTORE 800: FOR i=1 TO 30: READ a,b: BEEP a/2,b: NEXT i
120 PAUSE 100: RESTORE 900: FOR i=1 TO 61: READ c,d: BEEP c/2,d: NEXT i
130 PAUSE 120: RESTORE 1000: FOR i=1 TO 57: READ e,f: BEEP e/3,f: NEXT i
140 RESTORE 1010: PAUSE 150: FOR i=1 TO 96: READ g,h: BEEP g/5,h: NEXT i
150 PAUSE 120: GO TO 100
800 DATA 1,2,1,7,.5,7,.5,9,.5,7,.5,6,1,4,1,4,1,4,1,9,.5,9,.5,11,.5,9,.5,7,1,6,1,2,1,2,1,11,.5,11,.5,12,.5,11,.5,9,1,7,1,4,.5,4,.5,4,1,2,1,9,1,6,3,7
900 DATA 1,0,.75,5,.25,5,1,5,1,7,.75,9,.25,9,1.5,9,.5,9,.5,7,.5,9,1,10,1,4,1,7,1.5,5,1,0,.75,5,.25,5,1,5,1,7,.75,9,.25,9,1.5,9,.5,9,.5,7,.5,9,1,10,1,4,1,7,1.5,5,.5,12,.5,12,.5,9,1.5,14,.5,12,.5,12,.5,10,1.5,10,.5,10,.5,10,.5,7,1.5,12,.5,10,.5,10,.5,9,1,9,1,0,.75,5,.25,5,1,5,1,7,.75,9,.25,9,1.5,9,.5,9,.5,7,.5,9,1,10,1,4,1,7,1,5
1000 DATA 1,12,.75,11,.25,9,1.5,7,.5,5,1,4,1,2,1.5,0,.5,7,1.5,9,.5,9,1.5,11,.5,11,3,12,.5,12,.5,12,.5,11,.5,9,.5,7,.75,7,.25,5,.5,4,.5,12,.5,12,.5,11,.5,9,.5,7,.75,7,.25,5,.5,4,.5,4,.5,4,.5,4,.5,4,.25,4,.25,5,1.5,7,.25,5,.25,4,.5,2,.5,2,.5,2,.25,2,.25,4,1.5,5,.25,4,.25,2,.5,0,1,12,.5,9,.75,7,.25,5,.5,4,.5,5,1,4,1,2,4,0
1010 DATA 1,0,1,9,1,7,1,5,3,0,.5,0,.5,0,1,0,1,9,1,7,1,5,4,2,1,2,1,10,1,9,1,7,4,4,1,14,1,12,1,10,1,7,4,9,1,0,1,9,1,7,1,5,4,0,1,0,1,9,1,7,1,5,3,2,1,2,1,2,1,10,1,9,1,7,1,12,1,12,1,12,1,12,1,14,1,12,1,10,1,7,4,5,1,9,1,9,2,9,1,9,1,9,2,9,1,9,1,12,1.5,5,.5,7,4,9,1,10,1,10,1,10,1,10,1,10,1,9,1,9,.5,9,.5,9,1,9,1,7,1,7,1,9,4,7,1,9,1,9,2,9,1,9,1,9,2,9,1,9,1,12,1.5,5,.5,7,4,9,1,10,1,10,1,10,1,10,1,10,1,9,1,9,.5,9,.5,9,1,12,1,12,1,10,1,7,4,5
8999 STOP
9000 RESTORE 9000: FOR i=USR "a" TO USR "b"+7: READ r: POKE i,r: NEXT i: RETURN
9500 DATA 60,126,255,255,255,255,126,60
9510 DATA 255,129,129,129,129,129,129,255
9999 INK 9
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
