--- title: "Merry Christmas Message" id: 57155 type: "computer_media" slug: "merry-christmas-message-3" url: "http://localhost/computer_media/merry-christmas-message-3/" markdown_url: "http://localhost/computer_media/merry-christmas-message-3.md" published_at: "2024-10-04T00:59:26+00:00" modified_at: "2026-04-03T07:58:42+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/104_XMAS.png" excerpt: "A festive Christmas card program combines scrolling inverse-video text, block-graphic decorations, and embedded machine code routines for smooth animated effects." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Ryan Gray" slug: "ryan-gray" taxonomy: "indiv" url: "http://localhost/indiv/ryan-gray/" genre: - name: "Holiday" slug: "holiday" taxonomy: "genre" url: "http://localhost/type/holiday/" media_contents: - id: 56733 title: "Timex Sinclair Public Domain Library Tape 1002" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1002/" media_type: "Program" programmers: - name: "Ryan Gray" slug: "ryan-gray" taxonomy: "indiv" url: "http://localhost/indiv/ryan-gray/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/104_XMAS.png" media_type_tags: "Holiday" --- # Merry Christmas Message This ZX81/TS1000 program displays an animated Christmas greeting with a scrolling message and a decorative tree scene rendered using block graphics. It embeds two machine code routines directly in a REM statement at line 1: one routine (called via USR 16550) appears to perform a fast block memory copy or clear, and another (USR 16514) provides a delay or synchronisation function. The scrolling text in line 31/44 alternates between a plain string (A$) and an inverse-video version (B$) to create a flashing effect as the message moves across the screen. Lines 999–1060 form a diagnostic/loader section that prints and verifies the hex data for the machine code, and line 2000 saves the program. *** ## Program Analysis ### Program Structure The program is divided into three functional sections: 1. **Initialisation and display setup (lines 1–28):** The REM statement at line 1 stores two machine code routines. Lines 10–28 call the first routine, define the scrolling strings, draw the static scene using block graphics, and configure display settings via `POKE 16418`. 2. **Main animation loop (lines 29–60):** A `FOR` loop scrolls the greeting message across line 18, alternating between plain and inverse-video versions of the string for a flashing effect, with a machine code delay called between frames. 3. **Diagnostic/loader section (lines 999–2060):** Lines 999–1060 print and verify the hex content of the machine code area for development purposes. Line 2000 saves the program and line 2010 returns to the main entry point. ### Machine Code Routines Two machine code routines are embedded in the `REM` at line 1. The REM data begins at address 16514 (the first byte after the line’s length bytes), and a second entry point is at 16550. | Entry point | Called at | Apparent function | | --- | --- | --- | | `USR 16514` | Line 40 | Timing delay / frame sync between scroll steps | | `USR 16550` | Line 10 | Fast block memory operation (copy or clear using LDIR) | The hex string in line 1000 matches the REM content: key Z80 mnemonics visible in the byte sequence include `ED B8` (LDDR), `ED 52` (SBC HL,DE), `E5` (PUSH HL), `D1` (POP DE), and `C9` (RET). The routine at 16550 loads a 16-bit address from `(16448)` (the ZX81 D_FILE system variable), computes offsets, and performs a block transfer — consistent with manipulating the display file. The `HALT` byte `76` appears twice at offset +36/+37, used as a padding or end-of-routine marker. ### Display Techniques The static scene on lines 20–25 uses ZX81 block graphic characters to render a stylised Christmas tree and a fireplace-like border. The tree silhouette is built from `\''` (▀) and `\':` (▛) characters, with a trunk suggested by `\::` (▌) pairs. The bottom border uses `\:.\..` sequences to form a solid floor line. The scrolling animation on lines 29–50 uses two pre-built strings of equal length: `A$` contains the message with normal characters, and `B$` contains the same text with inverse-video characters (e.g. `%M%E%R%R%Y`). On each iteration, `B$` is printed first (line 31), the machine code delay runs (line 40), then `A$` is printed (line 44), creating a flicker/flash effect as the text scrolls. ### Key BASIC Idioms - `POKE 16418,0` and `POKE 16418,2` (lines 26/28) manipulate the `MARGIN` or a related system variable to control display scrolling behaviour — specifically suppressing the automatic scroll prompt. - `FOR A=1 TO LEN A$-30 STEP 2` (line 29) steps through the string two characters at a time, since each display position consumes one character in the ZX81’s non-collapsed display file. - `PRINT AT 0,INT (RND*32);"%."` (line 30) scatters inverse-video dots randomly across the top row on each frame, simulating falling snow. - `GOTO 29` (line 60) creates an infinite loop that continuously replays the scrolling animation. ### Diagnostic Section Lines 999–1060 appear to be a development aid. Line 1000 defines a string containing the expected hex bytes of the machine code. Lines 1030–1060 then `PEEK` each byte from address 16514 to 16600 and print it as a two-character hex string using the expression `CHR$ (28+INT (B/16))` — offset 28 from ASCII space maps digits 0–9 and letters A–F by exploiting the ZX81 character set layout where digits start at code 28. ### Notable Anomalies - Line 10 assigns the result of `USR 16550` to `A`, but the return value is not used; the call is purely for its side effect on the display file. - The strings `A$` and `B$` include long runs of spaces at start and end, acting as padding to ensure the message scrolls fully on and off screen without boundary errors in the substring slice `A$(A+1 TO A+30)`. - The `STEP 2` on line 29 means only odd-indexed starting positions are used, which is consistent with the ZX81 display file structure where each character cell occupies a predictable offset. ## Source Code ``` 1 REM 2A10401291ED4211430ED52E511210ED52D118C1EDB8EB6202B368010FBC976766162AC40237EFE76284368018F610F4C9 10 LET A=USR 16550 11 LET A$=" MERRY CHRISTMAS .''..''.---'.!!% . " 12 LET B$=" %M%E%R%R%Y %C%H%R%I%S%T%M%A%S :: :: ---'.!!% . " 20 PRINT AT 13,0;"% % % % % '''''' ''''''% % % % % % % '''''' ''''% % % '''' ''% % '' ':: ,,~~ :: ,,~~ :" 21 FOR A=17 TO 21 22 PRINT AT A,0;": :" 23 NEXT A 25 PRINT AT 21,0;":..............................................................:" 26 POKE 16418,0 27 PRINT AT 22,0;"% % % % % % % % % % % % % % % % % % % % % % % % % %R%Y%A%N% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % " 28 POKE 16418,2 29 FOR A=1 TO LEN A$-30 STEP 2 30 PRINT AT 0,INT (RND*32);"%." 31 PRINT AT 18,1;B$(A TO A+29) 40 LET Z=USR 16514 44 PRINT AT 18,1;A$(A+1 TO A+30) 50 NEXT A 60 GOTO 29 999 REM CODE 1000 LET A$="2A1040114300ED52E5112100ED52D1018C01EDB8EB06202B308010FBC9767606162A0C40237EFE762804368018F610F4C9" 1010 PRINT A$ 1020 PRINT ,, 1030 FOR A=16514 TO 16600 1040 LET B=PEEK A 1050 PRINT CHR$ (28+INT (B/16));CHR$ (28+B-(INT (B/16))*16);" "; 1060 NEXT A 2000 SAVE "1010%4" 2010 GOTO 1 ```