Christmas Card

This file is part of Long Island Sinclair Timex (LIST) User Group Library Tape #3.5. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Holiday

Draws a night scene with snowy ground, a green tree hung with coloured UDG baubles and topped with a star, a large yellow star in the sky and scattered small stars, then scrolls a double-height greeting along a white band near the bottom of the screen while playing carols with BEEP. A routine at line 9000 lets the user type a new message and prints (and LPRINTs) a replacement DATA line for it.

A REM credits the program to Tony Samuels, from Your Spectrum Dec/Jan 85, entered by Floyd Chrysler. The tape holds two saves: “Xmas” with a long message, and “xlist”, the same program with a shorter message in line 570.

Program Analysis

Program Structure

Lines 10–340 draw the scene with PLOT/DRAW loops and UDGs a (small star), b (bauble) and t (tree-top star). Line 360 POKEs a 72-byte routine to 65400. Lines 400–410 decode the message, and 420–470 print one character at a time, call the routine and play the next note from the DATA at 500–540.

Scrolling Message

Each character is printed invisibly (black on black) at the top-left of the screen. The machine code at 65400 shifts rows 19 and 20 of the display file left by one cell with LDIR, then copies the eight pixel bytes of the top-left cell into the vacated right-hand cells, writing each byte twice so the character appears at double height.

Notable Techniques

  • The message in line 570 is stored obfuscated: each character is recovered as CHR$ (255-(m-PEEK f)), using ROM bytes as the key.
  • The ground line is built with a random walk, LET a=a+INT (RND*3)-1, clamped between 32 and 60 pixels.
  • The small stars are placed only on empty cells by testing ATTR (y,x)<>0.

Potential Issues

  • Because the message key is read from the ROM, DATA produced on one machine decodes correctly only on a machine with the same ROM bytes.

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.

Source Code

    1 REM christmas card                  From Your Spectrum              Dec/Jan 85                      By Tony Samuels                 entered by                      Floyd Chrysler                                        
   10 CLEAR 65399: BORDER 0: PAPER 0: INK 0: CLS : INK 7
   20 DATA 0,8,8,62,8,8,8,8: RESTORE : FOR f=0 TO 7: READ z: POKE USR "t"+f,z: NEXT f
   30 DATA 0,0,0,0,1,0,0,0,0,2,64,0,0,0,16,0: FOR f=0 TO 15: READ a: POKE USR "a"+f,a: NEXT f
   40 LET a=50
   50 FOR f=0 TO 255
   60 PLOT f,0: DRAW 0,a
   70 LET a=a+INT (RND*3)-1
   80 IF a<32 THEN LET a=32
   90 IF a>60 THEN LET a=60
  100 NEXT f
  110 FOR f=17 TO 14 STEP -1: PRINT AT f,23; PAPER 1;" ": NEXT f
  120 LET a=10: FOR f=180 TO 200: PLOT f,30: DRAW 0,a: LET a=a+INT (RND*3)-1: NEXT f
  130 INK 4: LET a=30: FOR f=64 TO 160: PLOT 188,f
  140 DRAW -a,0: DRAW a*2,0
  150 LET a=a-.3
  170 NEXT f
  180 DATA 4,23,6,23,7,22,7,24,8,23,9,22,10,24,11,21,11,25,12,23,13,22,13,25
  190 FOR f=0 TO 11: READ x,y: PRINT AT x,y; INK RND*6+1; PAPER 4;"b": NEXT f
  200 INK 6
  210 LET a=0: FOR f=175 TO 165 STEP -1: PLOT 30,f: DRAW -a,0: DRAW a*2,0: LET a=a+.25: NEXT f: FOR f=164 TO 146 STEP -1: PLOT 30,f: DRAW -a,0: DRAW 2*a,0: LET a=a-.16: NEXT f
  220 LET a=2.5: FOR f=1 TO 10: PLOT 30-f,165: DRAW 0,a: DRAW 0,-a*2: PLOT 30+f,165: DRAW 0,a: DRAW 0,-a*2: LET a=a-.25: NEXT f
  230 PLOT 26,170: DRAW -5,5: PLOT 34,170: DRAW 5,5: PLOT 25,160: DRAW -7,-13: PLOT 36,160: DRAW 7,-13
  240 PRINT AT 1,23;"t"
  300 FOR f=0 TO 30
  310 LET x=INT (RND*32): LET y=INT (RND*12)
  320 IF ATTR (y,x)<>0 THEN GO TO 310
  330 PRINT AT y,x; INK 7;"a"
  340 NEXT f
  350 PRINT AT 19,0; INK 2; PAPER 7;"                                                                  "
  360 RESTORE 550: FOR f=65400 TO 65471: READ p: POKE f,p: NEXT f
  400 RESTORE 570: LET m$="": FOR f=1 TO 1000: READ m: IF m=999 THEN GO TO 410
  405 LET m$=m$+CHR$ (255-(m-PEEK (f))): NEXT f
  410 RESTORE 500: LET m$=m$+"    ": LET f=f+4
  420 LET c=1
  430 LET c$=m$(c): PRINT AT 0,0; INK 0; PAPER 0;c$: LET c=c+1
  440 IF c=f THEN GO TO 420
  450 READ b1,b2: IF b1=999 THEN RESTORE 500: GO TO 450
  460 LET l=USR 65400: BEEP b1/4,b2
  470 GO TO 430
  500 DATA 1,7,1,7,1,7,1,9,1,7,1,7,2,2,1,4,1,2,1,4,1,6,2,7,2,7,1,7,1,7,1,7,1,9,1,7,1,7,2,2,1,4,1,2,1,4,1,6,2,7,2,7,1,14,1,12,1,11,1,9,1,11,1,9,2,7,1,4,1,2,1,4,1,6,2,7,2,7,1,2,1,2,1,4,1,6,1,7,1,7,2,9,1,14,1,12,1,11,1,9,2,7,2,12,4,7
  510 DATA 1,11,.5,9,1,7,.5,4,.5,6,.5,7,.5,6,1.5,4,1,11,.5,9,1,7,.5,4,.5,6,.5,7,.5,6,1.5,4,1,7,.5,7,1,9,.5,9,1,11,.5,11,.5,14,.5,12,.5,11,.5,9,.5,11,.5,9,1,7,.5,6,3,4,1,6,.5,9,1,7,.5,7,1,7,.5,2,1,7,.5,4,1.5,7,1,7,.5,7,1,7,.5,2,1,7,.5,4,1.5,7,1,7,.5,7,1,9,.5,11,1,12,.5,11,1,9,.5,11,1,7,.5,7,1,7,.5,2,1,7,.5,4,3,7
  520 DATA 1,7,1,12,.5,12,.5,14,.5,12,.5,11,1,9,1,5,1,9,1,14,.5,14,.5,16,.5,14,.5,12,1,11,1,7,1,11,1,16,.5,16,.5,17,.5,16,.5,14,1,12,1,9,.5,7,.5,7,1,9,1,14,1,11,2,12
  530 DATA 1,7,1,12,1,12,1,12,2,11,1,11,1,12,1,11,1,9,2,7,1,14,1,16,.5,12,.5,14,.5,16,.5,17,1,19,1,7,.5,7,.5,7,1,9,1,14,1,11,2,12
  540 DATA 999,999
  550 DATA 6,8,33,97,80,229,209,27,197,1,31,0,237,176,1,225,0,9,193,16,240,6,8,33,129,80,229,209,27,197,1,31,0,237,176,1,225,0,9,193,16,240
  560 DATA 33,0,64,17,127,80,6,4,126,18,20,18,20,36,16,248,235,1,224,7,237,66,235,123,254,159,40,234,201,0
  570 DATA 358,175,398,398,329,272,180,188,251,232,257,248,233,168,213,418,415,165,407,466,478,426,405,187,251,303,349,380,279,139,362,416,339,183,182,380,409,402,466,418,198,194,409,392,409,466,478,372,196,238,233,363,418,203,164,400,452,223,270,239,182,257,330,315,314,328,179,226,392,203,218,420,365,363,370,154,432,351,364,464,417,345,363,251,476,289,143,391,279,200,233,333,230,241,478,464,464,464,478,999
 8999 STOP 
 9000 PAPER 7: INK 0: BORDER 1
 9001 REM To create your own              message enter go to             9000.  You will be              asked for your message          and then given the data         statement you can use           to replace line 570             above.                 
 9010 INPUT "TYPE IN MESSAGE ............"; LINE m$
 9015 DIM m(LEN m$)
 9020 FOR f=1 TO LEN m$
 9030 LET c=CODE m$(f): LET m(f)=255-c+PEEK f
 9040 NEXT f
 9090 CLS : PRINT " DATA ";
 9091 LPRINT " DATA ";
 9100 FOR f=1 TO LEN m$
 9110 PRINT m(f);",";
 9120 LPRINT m(f);",";
 9130 NEXT f
 9140 PRINT "999": LPRINT "999"
 9150 STOP

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