--- title: "Merry Christmas Message" id: 57140 type: "computer_media" slug: "merry-christmas-message" url: "http://localhost/computer_media/merry-christmas-message/" markdown_url: "http://localhost/computer_media/merry-christmas-message.md" published_at: "2024-10-04T00:14:47+00:00" modified_at: "2026-03-30T21:19:34+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/89_XMAS.png" excerpt: "A festive \"MERRY CHRISTMAS\" greeting driven by a self-modifying Z80 machine code routine tucked inside a REM statement — see how it works." 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/89_XMAS.png" media_type_tags: "Holiday" --- # Merry Christmas Message This program displays a “MERRY CHRISTMAS” greeting using a machine code routine embedded in a REM statement at line 1. The machine code, stored from address 16514 onward, is a Z80 routine that manipulates the display — it uses register pairs and relative jumps (DJNZ loops) to write directly to screen memory. Lines 3 and 5 use POKE 16515 to modify a byte within the REM/machine code area itself, effectively self-modifying the routine’s behaviour between two calls via RAND USR 16514. The PRINT AT statement at line 8 positions the greeting text at row 10, column 8, and the GOTO 2 loop continuously cycles the display effect. *** ## Program Analysis ### Program Structure The program is short but layered. Line 1 holds a REM statement whose body is raw Z80 machine code. Lines 2–6 form the main execution loop: call the machine code routine, poke a new value into it, call it again with the modified byte, then repeat forever via `GOTO 2`. Line 7 is a `SAVE` command that would save the program. Line 8 prints the greeting, and line 9 loops back — though line 8 and 9 are never reached by the main loop at line 6, suggesting the program was perhaps edited or the loop is intended to cycle only through lines 2–6. ### Machine Code in the REM Statement On the ZX81/TS1000, a REM statement’s text bytes begin at address 16514 (the byte immediately after the line-length and REM token). The bytes stored there are: | Offset | Hex | Z80 Mnemonic | Notes | | --- | --- | --- | --- | | 0 | `3E 86` | LD A, 86h | Load accumulator with 134 | | 2 | `2A 0C 40` | LD HL, (400Ch) | Load HL from display address area | | 5 | `06 20` | LD B, 32 | Counter for 32 bytes | | 7 | `23` | INC HL | Advance pointer | | 8 | `77` | LD (HL), A | Write A to screen memory | | 9 | `10 FC` | DJNZ -4 | Loop 32 times | | 11 | `06 14` | LD B, 20 | Counter for 20 rows | | 13 | `23 23` | INC HL / INC HL | Skip two bytes | | 15 | `77` | LD (HL), A | Write pattern | | 16 | `11 1F 00` | LD DE, 31 | Row stride | | 19 | `19` | ADD HL, DE | Advance by one row | | 20 | `77` | LD (HL), A | Write pattern | | 21 | `10 F6` | DJNZ -10 | Loop 20 rows | | 23 | `23` | INC HL | | | 24 | `06 20` | LD B, 32 | Counter for 32 bytes | | 26 | `23` | INC HL | | | 27 | `77` | LD (HL), A | Write pattern | | 28 | `10 FC` | DJNZ -4 | Loop 32 times | | 30 | `C9` | RET | Return to BASIC | The routine draws a rectangular border pattern around the screen by writing the value in the accumulator to a run of display file bytes. The first call (line 2) uses whatever byte is currently at offset 1 of the REM (initially `86h` = 134, a ZX81 graphics character). Line 3 then POKEs address 16515 (offset 1, the immediate operand of `LD A, n`) to 6, changing the character written. Line 4 calls the routine again with this new value, creating an animation toggle effect. ### Self-Modification Technique The key idiom here is patching the machine code’s own immediate operand through `POKE 16515`. Because the `LD A, n` instruction’s operand sits at a known, fixed address within the REM statement, lines 3 and 5 alternate the value between 6 and 134 (decimal), causing the border pattern to flash between two different graphic characters on each loop iteration. This is a classic ZX81 self-modifying code pattern used to squeeze animation out of minimal ROM calls. ### Key BASIC Idioms - `RAND USR 16514` — the standard ZX81 idiom for calling a machine code address. `RANDOMIZE USR` discards the return value without error. - `POKE 16515, n` — directly modifies the second byte of the REM statement (the operand of `LD A, n`), achieving self-modification from BASIC. - `GOTO 2` at line 6 creates an infinite animation loop over lines 2–5. ### Unreachable Lines Lines 8 and 9 (`PRINT AT 10,8;"MERRY CHRISTMAS"` and `GOTO 2`) are never reached during normal execution because line 6 unconditionally jumps back to line 2. These lines may be a remnant of an earlier version where the loop included a print step, or they may have been intended as a fallback that was later superseded by the machine code display routine. ### Notable Observations - The machine code references address `400Ch`, which on the ZX81 falls within the display file area — confirming the routine writes directly to video RAM. - The two alternating values, 6 and 134 (= 6 + 128), are a normal character and its inverse-video equivalent, producing a blinking border effect. - The tight DJNZ loops make the routine fast enough to produce visible flicker animation without any additional PAUSE or delay. ## Source Code ``` 1 REM \3E\86\2A\0C\40\06\20\23\77\10\FC\06\14\23\23\77\11\1F\00\19\77\10\F6\23\06\20\23\77\10\FC\C9 2 RAND USR 16514 3 POKE 16515,6 4 RAND USR 16514 5 POKE 16515,134 6 GOTO 2 7 SAVE "1008%9" 8 PRINT AT 10,8;"MERRY CHRISTMAS" 9 GOTO 2 ```