Christmas Special

Date: 1983
Type: Program
Platform(s): TS 2068

This program renders an animated starfield scene with custom UDG characters and scrolling text banners, accompanied by a musical fanfare. Seven UDGs (labeled “a” through “f” and “e”) are defined using BIN literals to create pixel-art sprites — likely figures and decorative elements — by poking 8-byte bitmaps into the UDG area via USR. The drawing section uses PLOT and DRAW commands to construct geometric shapes (possibly a building or trophy outline) and fills regions using nested FOR loops. Two string variables, a$ and b$, each 65 characters wide, implement horizontal marquee scrolling at screen rows 3 and 6 by rotating characters through string slicing. The BEEP-based music routines at lines 4000–5110 play a short repeating fanfare with recognizable rhythmic patterns using pitch values and durations.


Program Analysis

Program Structure

The program is organized into several clearly separated phases:

  1. Initialization (lines 5–80, 100–570): Variables are set and seven UDG characters are defined via POKE.
  2. Scene setup (lines 1000–1100): Scrolling string buffers are initialized and the screen is cleared with black paper.
  3. Background drawing (lines 2000–2010): Stars (dots) and UDG \f characters are scattered randomly.
  4. PLOT/DRAW artwork (lines 3000–3270): Geometric shapes are drawn and filled using nested loops.
  5. Scrolling loops (lines 3300–3999): Two marquee text rows scroll indefinitely, with music subroutine calls between passes.
  6. Music subroutines (lines 4000–5110): BEEP-based fanfares organized into modular subroutines.

UDG Character Definitions

Lines 10–570 define six UDGs using POKE USR "x"+n, BIN xxxxxxxx to write 8-byte bitmaps. The UDGs defined are:

UDGEscapeNotes
"e"\eAsymmetric figure, likely a person or alien sprite
"a"\aMirror/variant of \e; row 6 missing (line 170 absent)
"b"\bDense rectangular shape, possibly a trophy or object
"c"\cHorizontal line in center row only (row 3 = BIN 11111111); acts as a spacer/divider
"d"\dMirror of \b
"f"\fDiamond/star shape; used in the starfield foreground

Note that UDG "a" is missing its row 6 definition (line between 160 and 180 is absent), so USR "a"+6 retains its previous value — a minor anomaly that may affect the sprite’s appearance.

Background and Scene Drawing

Lines 2000–2010 scatter 250 dot characters and 52 \f UDG instances at random screen positions to create a starfield. The \f UDG (a diamond pattern) is placed in INK 4 (green) to differentiate foreground stars.

Lines 3000–3270 use PLOT and DRAW to render what appears to be a building or monument silhouette, complete with a doorway cutout (the conditional skip at lines 3100–3110) and a curved roof drawn with incrementing/decrementing loop variable a. The nested fill loops in 3090–3190 use floating-point increments (a+.7, a-.7) to approximate diagonal edges.

Scrolling Text Technique

Two string variables implement horizontal marquee scrolling:

  • a$ (65 characters): scrolls right-to-left at row 3 by rotating the last character to the front: LET a$=a$(64)+a$(TO 63).
  • b$ (65 characters): scrolls left-to-right at row 6 by rotating the first character to the end: LET b$=b$(2 TO LEN b$)+b$(1).

Each loop prints only the first 32 characters of the buffer (a$(TO 32)) to fill one screen row. PAUSE 20 and PAUSE 10 control scroll speed. The strings embed UDG characters (\b, \c, \e, \a, \d) to display sprite-based content within the scrolling banner.

Music Subroutines

The music is organized as a small call tree:

  • GO SUB 4000 — master fanfare: calls 4005, then 4050, then 4005, then falls through to 5100.
  • GO SUB 4005 — plays three beeps via GO SUB 5050, then a melodic phrase (lines 4010–4040).
  • GO SUB 4050 — plays a short five-note motif.
  • GO SUB 5050 — plays three identical beeps at pitch 10.
  • GO SUB 5100 — plays a descending four-note phrase with a long final note, then pauses.

Line 4000 uses GO TO 5100 rather than GO SUB 5100: RETURN, relying on 5110 RETURN to unwind back to the original caller — a stack-efficient tail-call pattern.

Notable Anomalies

  • Line 3075 contains REM go to 3200, indicating the PLOT/DRAW fill section (3090–3190) was intentionally bypassed during development but later re-enabled by removing or not executing a GO TO 3200. The REM is left as a comment artifact.
  • Line 3300 uses variable i as the loop start (FOR n=i TO 64), but i is last set during the PLOT/DRAW section (line 3230, loop variable). This couples the drawing phase to the scroll loop timing and means the first scroll pass may be shorter than subsequent ones.
  • Variables sk and s initialized at line 5 and the DIM c$(32) array are never used in the visible program — likely remnants of a removed gameplay or scoring feature.
  • Line 4999 (STOP) is unreachable dead code between the music subroutines.

Appears On

LIST user group library cassette with games, home finance, education, darkroom formulas, an OSCAR 10 satellite tracker and programming utilities across two sides.

Related Articles

Here are two programs that give a moving graphics representation of the holiday spirit.

Image Gallery

Source Code

    5 LET sk=0: LET s=0: DIM c$(32)
   10 POKE USR "e",BIN 00000101
   20 POKE USR "e"+1,BIN 00000010
   30 POKE USR "e"+2,BIN 00000010
   40 POKE USR "e"+3,BIN 10000110
   50 POKE USR "e"+4,BIN 11111111
   60 POKE USR "e"+5,BIN 01111110
   70 POKE USR "e"+6,BIN 01010101
   80 POKE USR "e"+7,BIN 01010101
  100 POKE USR "a",BIN 10100000
  120 POKE USR "a"+1,BIN 01000000
  130 POKE USR "a"+2,BIN 01000000
  140 POKE USR "a"+3,BIN 01100001
  150 POKE USR "a"+4,BIN 11111111
  160 POKE USR "a"+5,BIN 01111110
  180 POKE USR "a"+7,BIN 10101010
  200 POKE USR "b",BIN 10100000
  210 POKE USR "b"+1,BIN 10110001
  220 POKE USR "b"+2,BIN 10110001
  230 POKE USR "b"+3,BIN 11111110
  240 POKE USR "b"+4,BIN 11111100
  250 POKE USR "b"+5,BIN 01000100
  270 POKE USR "b"+6,BIN 01000100
  280 POKE USR "b"+7,BIN 11111110
  300 POKE USR "c",BIN 00000000
  310 POKE USR "c"+1,BIN 00000000
  320 POKE USR "c"+2,BIN 00000000
  330 POKE USR "c"+3,BIN 11111111
  340 POKE USR "c"+4,BIN 00000000
  350 POKE USR "c"+5,BIN 00000000
  360 POKE USR "c"+6,BIN 00000000
  370 POKE USR "c"+7,BIN 00000000
  400 POKE USR "d",BIN 00000101
  410 POKE USR "d"+1,BIN 10001101
  420 POKE USR "d"+2,BIN 10001101
  430 POKE USR "d"+3,BIN 01111111
  440 POKE USR "d"+4,BIN 00111111
  450 POKE USR "d"+5,BIN 00100010
  460 POKE USR "d"+6,BIN 00100010
  470 POKE USR "d"+7,BIN 01111111
  500 POKE USR "f",BIN 00011000
  510 POKE USR "f"+1,BIN 00011000
  520 POKE USR "f"+2,BIN 00111100
  530 POKE USR "f"+3,BIN 00111100
  540 POKE USR "f"+4,BIN 01111110
  550 POKE USR "f"+5,BIN 01111110
  560 POKE USR "f"+6,BIN 00011000
  570 POKE USR "f"+7,BIN 00011000
 1000 LET a$="                                                  \b\c\e\e\c\e\e\c\e\e\c\e\e ": LET b$="                                                 \a\a\c\a\a\c\a\a\c\a\a\c\d "
 1100 PAPER 0: BORDER 7: INK 7: CLS 
 2000 FOR n=1 TO 250: PRINT AT INT (22*RND),INT (32*RND);".": NEXT n
 2010 INK 4: FOR n=1 TO 50: PRINT AT INT (RND*10)+8,INT (RND*21);"\f": NEXT n: PRINT AT 9,25;"\f";AT 13,27;"\f"
 3000 INK 7: PLOT 0,10: DRAW 255,10: PLOT 0,20: DRAW 255,10
 3010 PLOT 193,35: DRAW 30,0: DRAW 0,15: DRAW -15,10: DRAW -15,-10: DRAW 0,-15
 3020 DRAW -20,30: DRAW 0,15: DRAW 20,-30
 3030 PLOT 173,80: DRAW 15,10: DRAW 20,-30
 3040 PLOT 189,90: DRAW 15,-10: DRAW 20,-30
 3050 PLOT 184,88: DRAW 0,8: DRAW 8,0: DRAW 0,-8
 3060 PLOT 180,84: DRAW 0,18: DRAW 5,-6
 3070 PLOT 180,102: DRAW 8,0: DRAW 4,-6
 3075 REM go to 3200
 3090 FOR n=195 TO 221: FOR i=35 TO 49
 3100 IF n>210 AND n<216 AND i<44 AND i>37 THEN GO TO 3120
 3110 PLOT n,i
 3120 NEXT i: NEXT n
 3130 LET a=50: FOR n=196 TO 208: FOR i=50 TO a
 3150 PLOT n,i
 3160 NEXT i: LET a=a+.7: NEXT n
 3170 LET a=58: FOR n=208 TO 220: FOR i=a TO 49 STEP -1
 3180 PLOT n,i
 3190 NEXT i: LET a=a-.7: NEXT n
 3200 FOR j=1 TO 2: LET i=52: FOR n=194 TO 176 STEP -1
 3210 PLOT n,1: DRAW 12,10
 3220 LET i=i+1.5: NEXT n
 3230 LET i=59: FOR n=209 TO 189 STEP -1
 3240 PLOT n,i: DRAW 15,-8
 3250 LET i=i+1.5: NEXT n
 3260 NEXT j
 3270 PLOT 192,38: LET a=38: FOR n=192 TO 173 STEP -1: PLOT n,a: DRAW 0,10: LET a=a+1.5: NEXT n
 3300 FOR n=i TO 64
 3310 PRINT AT 3,0;a$( TO 32)
 3320 LET a$=a$(64)+a$( TO 63)
 3330 PAUSE 20: NEXT n
 3335 GO SUB 4000
 3340 FOR n=1 TO 64
 3350 PRINT AT 6,0;b$( TO 32)
 3360 IF LEN b$>1 THEN LET b$=b$(2 TO LEN b$)+b$(1)
 3370 PAUSE 10: NEXT n
 3380 GO SUB 4000
 3999 GO TO 3300
 4000 GO SUB 4005: GO SUB 4050: GO SUB 4005: GO TO 5100
 4005 GO SUB 5050: PAUSE 20: GO SUB 5050: PAUSE 20
 4010 BEEP .25,10: BEEP .25,13: BEEP .27,6: BEEP .25,8: BEEP .75,10: PAUSE 30
 4030 BEEP .25,11: BEEP .25,11: BEEP .25,11: BEEP .1,11: BEEP .1,11: BEEP .25,11: BEEP .25,10: BEEP .25,10
 4040 BEEP .1,10: BEEP .1,10: BEEP .25,10
 4045 RETURN 
 4050 BEEP .25,8: BEEP .25,8: BEEP .25,10: BEEP .5,8: BEEP .5,13
 4055 RETURN 
 4999 STOP 
 5050 FOR n=1 TO 3: BEEP .25,10: NEXT n: RETURN 
 5100 BEEP .25,13: BEEP .25,11: BEEP .25,8: BEEP 1,6
 5110 PAUSE 50: RETURN 

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