--- title: "Merry Christmas Message" id: 57143 type: "computer_media" slug: "merry-christmas-message-2" url: "http://localhost/computer_media/merry-christmas-message-2/" markdown_url: "http://localhost/computer_media/merry-christmas-message-2.md" published_at: "2024-10-04T00:46:51+00:00" modified_at: "2026-03-30T21:19:32+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/92_XMAS.png" excerpt: "A festive \"MERRY CHRISTMAS\" message scrolls and bounces across the screen in inverse video, using clever substring tricks to create a smooth corner-wrap effect." 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/" 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" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/92_XMAS.png" media_type_tags: "Holiday" --- # Merry Christmas Message This program displays a scrolling “* MERRY CHRISTMAS” message (with inverse-video letters) across the ZX81/TS1000 screen. The main loop (lines 2–11) prints the message string at successive column positions across all 22 rows, filling the screen character by character. When the message reaches the bottom-right corner (row 21, column 16), a special corner-handling routine at lines 30–34 prints a shrinking tail of the string along the last row, before transitioning to a full-screen asterisk-fill sequence (lines 14–16) and then a horizontal scroll-off effect (lines 17–20). The program uses AT-based character-by-character placement and substring slicing (the TO operator) to create smooth scrolling effects within BASIC’s constraints. *** ## Program Analysis ### Program Structure The program is divided into four functional sections: 1. **Main scroll loop (lines 1–11):** Initialises the message string `A$` (with inverse-video letters) and two counters `A` (row) and `B` (column), then prints `A$` at successive column positions across the full 22×32 display. 2. **Corner handler (lines 30–35):** When the message reaches row 21, column 16 (the point where the string would run off the right edge of the bottom row), this routine prints a shrinking substring of `A$` along the last row to simulate the tail disappearing off-screen. 3. **Full-screen asterisk fill (lines 14–16):** Fills every row with 32 asterisk characters, overwriting the display. 4. **Horizontal scroll-off (lines 17–20):** Prints progressively shorter trailing substrings of `A$` at row 0 from column 0, giving the impression the message slides off to the right. ### The Message String `A$` is defined as `"*%M%E%R%R%Y*%C%H%R%I%S%T%M%A%S"`. The `%`-prefixed characters are inverse-video letters, so the string renders as an asterisk followed by **MERRY** in inverse, then an asterisk, then **CHRISTMAS** in inverse — 16 characters in total. This length of exactly 16 characters is significant: it is half the 32-column screen width, which drives the corner-handling trigger condition. ### Main Scroll Loop Logic Lines 2–11 implement a nested loop using two plain variables rather than `FOR…NEXT`, giving finer control over when to branch elsewhere: - `B` counts columns 0–31; when it reaches 32 (line 6) it resets to 0 and increments the row `A`. - The special-case test at line 7 checks `A=21 AND B=16`: row 21 is the last row, and column 16 is where the 16-character string would start to be clipped by the right margin, triggering the corner routine. ### Corner-Wrap Routine (Lines 30–34) Starting at column 16 on row 21, the loop variable `V` begins at 16 (the full string length) and decrements by 1 each iteration. Each iteration prints `A$(1 TO V)` — a progressively shorter prefix of the string — at the current column, while `C` advances from 16 to 31. This creates the appearance that the message tail is scrolling off the right edge of the bottom row before control passes to the asterisk-fill section. ### Scroll-Off Effect (Lines 17–20) After the asterisk fill, the loop runs `A` from 16 down to 1, printing `A$(A TO 16)` at the top-left of the screen each iteration. Since `A$(A TO 16)` is a suffix of decreasing length (starting at the full 16 characters and shrinking to just the last character), this gives the impression that the message is scrolling off to the right. After this loop completes, `GOTO 1` restarts the entire sequence. ### Key BASIC Idioms and Techniques | Technique | Lines | Notes | | --- | --- | --- | | Manual loop with `IF…GOTO` | 2–11 | Avoids `FOR…NEXT` to allow mid-loop branching | | Substring slicing (`TO`) | 18, 19, 32 | Used to create both the scroll-off and tail-shrink effects | | Inverse-video in string literal | 1, 13 | `%`-prefix characters render as inverse video on screen | | `PRINT AT` for precise placement | 4, 15, 19, 32 | No cursor movement; every print is position-absolute | ### Anomalies and Notes - Line 13 redundantly re-assigns `A$` to the same value it already holds from line 1. This may be a precaution in case the routine at lines 14–35 is ever entered independently, but in normal flow it is unnecessary. - The `SAVE "1009%2"` at line 12 is never reached during normal execution (the loop at lines 4–11 never falls through to line 12). It appears to serve as a persistent storage line embedded in the listing. - After the corner routine ends with `GOTO 17` (line 35), the asterisk fill at lines 14–16 is bypassed, so the transition from corner-wrap to scroll-off occurs without the intermediate fill step on the first pass through that path. ## Source Code ``` 1 LET A$="*%M%E%R%R%Y*%C%H%R%I%S%T%M%A%S" 2 LET A=0 3 LET B=0 4 PRINT AT A,B;A$ 5 LET B=B+1 6 IF B=32 THEN GOTO 9 7 IF A=21 AND B=16 THEN GOTO 30 8 GOTO 4 9 LET B=0 10 LET A=A+1 11 GOTO 4 12 SAVE "1009%2" 13 LET A$="*%M%E%R%R%Y*%C%H%R%I%S%T%M%A%S" 14 FOR A=0 TO 21 15 PRINT AT A,0;"********************************" 16 NEXT A 17 FOR A=16 TO 1 STEP -1 18 LET B$=A$(A TO 16) 19 PRINT AT 0,0;B$ 20 NEXT A 21 GOTO 1 30 LET V=16 31 FOR C=16 TO 31 32 PRINT AT 21,C;A$(1 TO V) 33 LET V=V-1 34 NEXT C 35 GOTO 17 ```