--- title: "Bounce" id: 57436 type: "computer_media" slug: "bounce-3" url: "http://localhost/computer_media/bounce-3/" markdown_url: "http://localhost/computer_media/bounce-3.md" published_at: "2024-10-05T13:29:50+00:00" modified_at: "2026-03-30T21:17:55+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/237_Boun.png" excerpt: "A self-contained bouncing ball demo driven entirely by hand-crafted Z80 machine code hidden inside REM statements — no BASIC graphics commands involved at all." 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: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_contents: - id: 56736 title: "Timex Sinclair Public Domain Library Tape 1005" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1005/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/10/237_Boun.png" media_type_tags: "Demo" --- # Bounce This program implements a bouncing ball animation entirely in Z80 machine code, embedded in REM statements and executed via RAND USR 16908. The machine code manipulates display memory directly, using 16-bit address arithmetic to move a ball sprite around the screen and handle boundary collisions. Two REM lines carry the full binary payload: the first (line 0) contains the primary routine, and the second also line 0 (a known multi-line-zero trick) stores additional data tables and vectors. Line 2 contains patching notes for the developer, listing key addresses and byte values used to redirect execution flow. The program loops continuously via GOTO 1, re-entering the machine code on each pass. *** ## Program Analysis ### Program Structure The listing is minimal at the BASIC level, with almost all logic residing in Z80 machine code stored in `REM` statements: 1. **Line 0 (first)** — REM with an inverse-video title “BOUNCE”. 2. **Line 0 (second)** — REM containing the full machine code payload (approximately 280+ bytes of Z80 opcodes encoded as hex escapes). 3. **Line 1** — `RAND USR 16908` transfers control to the machine code at address 16908 (0x420C), which falls inside the second REM line’s data area. 4. **Line 2** — Developer commentary listing patch addresses and byte values needed to relocate or hook the routine. 5. **Lines 3–4** — `SAVE` followed by `GOTO 1` to continuously re-run the animation. ### Machine Code Entry and Memory Layout `RAND USR 16908` (decimal) equals `USR 0x420C`. On a TS2068/ZX Spectrum, the system variables area ends well below this, so 0x420C lands squarely in the second REM line’s payload. The code sets up its own internal pointers using absolute 16-bit addresses (`22 xx xx` = `LD (nnnn),HL`; `2A xx xx` = `LD HL,(nnnn)`), making the routine position-dependent at these fixed addresses. ### Display Memory Access The machine code accesses display RAM directly. Several instruction sequences load `HL` or `DE` with addresses in the `0x4000`–`0x5AFF` range (the Spectrum/TS2068 display file and attribute area). The pattern `19` (`ADD HL,DE`) combined with `71` (`LD (HL),C`) and short `DJNZ` loops (`10 Fx`) is a classic tight sprite-drawing idiom, writing pixels row by row across display lines. ### Key Z80 Idioms Identified - `11 xx xx` / `19` — Load DE with a stride value and repeatedly add to HL to step through display memory rows. - `10 Fx` — `DJNZ` short loops for pixel/attribute row iteration. - `ED 5B xx xx` — `LD DE,(nnnn)` to fetch ball position from a workspace variable. - `22 xx xx` / `2A xx xx` — Store/recall 16-bit ball coordinates in fixed workspace locations. - `7E B7` — `LD A,(HL); OR A` to test a display cell for non-zero content (collision detection). - `C3 xx xx` — Unconditional `JP` used for main loop branches and dispatch. - `18 xx` — Relative `JR` for short local branches. - `E5`/`E1` — `PUSH HL`/`POP HL` used to preserve the ball’s address across sub-operations. ### Bounce / Collision Logic The routine reads the ball’s current screen address from a workspace cell, draws the ball, then tests the target cell’s content. When `OR A` finds the cell non-zero (another pixel already present, i.e., a wall or boundary), the velocity component is negated by branching to an alternate delta-add path. The direction vectors appear to be stored as signed 16-bit offsets (e.g., `0x004D`, `0xFF B0`) applied via `ADD HL,DE` to the current display address, giving horizontal and vertical movement independently. ### Data Tables Near the end of the second REM block, a sequence of values `21 22 23 24 25 1C 1D 1E 1F 20 21 22 23 24 25 1C` appears to be a lookup table, likely encoding the ball sprite shape or a cyclic animation frame table, referenced by an index that increments on each frame. ### Developer Patch Notes (Line 2) Line 2 is a plain-text memo to the programmer listing addresses and patch bytes: | Label | Address | Value/Note | | --- | --- | --- | | CDE702 | — | Opcode bytes for a `JP 0x02E7`-style hook | | Q 217D40 | 0x407D | Workspace pointer (ball position low byte?) | | 222940 | 0x4029 | `LD (0x4029),HL` — stores a vector | | C3FC02 | — | `JP 0x02FC` — likely a BASIC interpreter re-entry | ### GOTO Loop `GOTO 1` at line 4 creates an infinite BASIC loop that re-executes `RAND USR 16908` on each iteration. In practice the machine code itself contains an internal loop (`18 C8`, `18 C1`, `C3 91 40`, etc.) and never returns to BASIC during normal animation; the `GOTO` serves as a safety net if the routine ever exits cleanly. ### Potential Anomalies - Two lines both numbered `0` — the second silently shadows or appends to the first depending on the interpreter’s line-lookup behaviour; this is intentional to pack the code before line 1. - The routine uses absolute addresses throughout, so it is not relocatable without the patches documented in line 2. - The `SAVE "1023%7"` on line 3 is reached via fall-through from line 1 only if `RAND USR` returns, which under normal operation it does not. ## Source Code ``` 0 REM % %B%O%U%N%C%E% 0 REM \0E\08\06\20\11\F7\02\2A\0C\40\E5\23\E5\71\19\71\E1\10\F8\23\23\06\16\11\1F\00\71\19\71\23\23\10\F9\E1\11\4B\01\19\E5\11\84\00\06\20\E5\71\19\71\E1\23\10\F8\E1\23\0E\00\11\9F\00\06\03\E5\71\19\71\E1\23\10\F8\E5\11\C8\00\19\22\40\40\36\34\21\00\04\22\46\40\E1\E5\11\B0\FF\19\22\48\40\36\36\21\DE\FE\22\50\40\E1\11\4D\00\19\22\3E\40\36\1C\21\E0\FF\22\42\40\21\DE\FF\22\44\40\18\09\2A\34\40\22\32\40\2A\46\40\2B\7C\B5\20\FB\3A\26\40\FE\FE\C8\06\21\2A\48\40\36\00\ED\5B\50\40\19\7E\B7\20\05\36\36\22\48\40\B7\28\22\05\28\FB\E5\2A\32\40\54\5D\29\29\19\29\22\32\40\7C\E6\06\C6\95\6F\26\41\5E\23\56\ED\53\50\40\E1\18\C8\E5\2A\7B\40\7E\32\26\41\32\36\41\23\7E\32\2C\41\32\58\41\23\7E\32\34\41\FE\36\28\07\23\22\7B\40\E1\18\A3\21\8A\41\22\7B\40\E1\18\86\00\40\44\34\3E\42\1C\48\50\36\00\00\DE\FF\20\00\E0\FF\22\00\00\21\8D\41\22\7B\40\C3\91\40\00\00\00\00\00\00\56\ED\53\42\40\E1\18\C2\06\35\2A\48\40\36\00\ED\5B\50\40\19\7E\4F\E6\F7\20\05\36\36\22\48\40\B1\CA\22\41\05\28\FA\00\E5\2A\32\40\54\5D\29\29\19\29\29\29\19\22\32\40\7C\E6\06\C6\91\6F\26\40\5E\23\56\ED\53\50\40\E1\18\C1\21\12\42\22\29\40\C3\FC\02\21\00\60\22\04\40\21\1C\42\22\29\40\C9\CD\2B\0F\C3\9E\41\00\00\06\00\F9\D4\C5\26\0D\76\00\00\02\00\FB\76\00\00\06\00\F9\D4\C5\27\0D\76\00\27\3E\00\27\34\27\00\32\2E\3D\00\00\21\22\23\24\25\1C\1D\1E\1F\20\21\22\23\24\25\1C 1 RAND USR 16908 2 REM STICK THIS SOMEWHERE AND CALL IT: CDE702 Q 217D40 222940 C3FC02 3 SAVE "1023%7" 4 GOTO 1 ```