--- title: "Ball" id: 57435 type: "computer_media" slug: "ball" url: "http://localhost/computer_media/ball/" markdown_url: "http://localhost/computer_media/ball.md" published_at: "2024-10-05T13:28:48+00:00" modified_at: "2026-03-30T21:17:55+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/10/236_Bal1.png" excerpt: "A pure machine code ball-bouncing demo hidden inside a REM statement — with a clever trick to break looping patterns using the frame counter." 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/236_Bal1.png" media_type_tags: "Demo" --- # Ball This program implements a ball-bouncing simulation using a machine code routine embedded in a REM statement at line 1. The machine code is invoked directly via RAND USR 16514, which jumps into the bytes stored in the REM line’s data area. The routine uses the ZX81’s display file to track and animate a bouncing ball, with a pseudo-random number generator to vary the ball’s trajectory. A SHIFT keypress injects the frame counter value into the RNG to break repetitive patterns, a technique common in games of this era to add entropy. *** ## Program Analysis ### Program Structure The program is minimal on the BASIC side — almost all logic lives in machine code. The BASIC lines serve only as a loader and launcher: 1. `LINE 1`: A `REM` statement containing the entire machine code routine as raw bytes. 2. `LINE 2`: `SLOW` — switches the display to slow (non-FAST) mode so the display file is active and the ball is visible. 3. `LINE 3`: `RAND USR 16514` — calls the machine code at address 16514, which is 2 bytes into the REM line’s data (past the `REM` token and the length bytes), effectively entering the routine directly. 4. `LINE 4`: A `REM` containing user instructions about pressing SHIFT to reset the RNG. 5. `LINE 5`: `SAVE` the program. 6. `LINE 6`: `LIST 2` — returns the display to line 2 after loading, hiding line 1’s raw bytes. ### Machine Code Usage The machine code is stored in the `REM` at line 1, starting at address 16514 (0x4082). `RAND USR 16514` jumps directly into it. The routine is self-contained and runs in an infinite loop, animating a ball across the ZX81 display file. Key features visible in the disassembly bytes include: - Use of `HL` and `DE` register pairs to track the ball’s position within the display file (which begins at a stored address in system variables). - A `DJNZ` loop (`0x10 0xF8`, `0x10 0xF9`) for scanning surrounding cells — typical for collision detection in ZX81 display-file manipulation. - Comparison against `0x76` (the `HALT` opcode, which the ZX81 uses as a newline/end-of-line marker in the display file) to detect screen edges. - A call to `0x415A` (likely a ROM keyboard scan routine) with a test for the SHIFT key (`0xFE` / `0xA7` / `0x38`), implementing the SHIFT-to-reseed behaviour described in line 4. - An `ED 52` (`SBC HL,DE`) instruction used to compute a displacement, feeding into the pseudo-random number generator. - Storage of the ball’s current address at `0x403C` and related state variables at nearby addresses (`0x4040`, `0x4044`, `0x4046`), all within the user RAM area just above the system variables. - The tail of the REM contains a small lookup table with direction vectors (`0xE0 0xFF`, `0x01 0x00`, `0x22 0x00`, `0x21 0x00`, `0x20 0x00`, `0xFF 0xFF`, `0xDE 0xFF`, `0xDF 0xFF`) representing eight possible ball movement directions as 16-bit signed offsets into the display file. - A subroutine near the end of the REM (`0xE5 0x2A 0x32 0x40 ...`) computes the display file row offset using repeated `ADD HL,HL` shifts and `ADD HL,DE` to multiply by the line width — a standard ZX81 display address calculation. ### Key BASIC Idioms - `RAND USR 16514`: The `RAND` keyword is used purely to discard the return value of `USR`; without it, the integer result would be assigned as the new random seed, which is harmless but tidy. - `SLOW` before the USR call ensures the display interrupt is running, which the routine relies on for timing and frame-counter entropy. - `LIST 2` at the end presents the program cleanly after a `LOAD`, hiding the raw machine code bytes of line 1 from casual view. ### RNG and Pattern-Breaking Technique The pseudo-random number generator operates on a seed stored in RAM. Because the ZX81’s SLOW mode increments a frame counter (at system variable `FRAMES`, address `0x4034`), pressing SHIFT causes the routine to XOR or mix the current frame count into the seed. This breaks any deterministic loop the ball may have entered, as described in the line 4 comment. The technique is a pragmatic solution to the limited entropy available on the platform. ### Direction Vector Table | Bytes (hex) | Signed 16-bit offset | Approximate direction | | --- | --- | --- | | E0 FF | -32 | Left one cell | | 01 00 | +1 | Right one byte | | 22 00 | +34 | Down one row | | 21 00 | +33 | Down-right diagonal | | 20 00 | +32 | Down-left diagonal | | FF FF | -1 | Left one byte | | DE FF | -34 | Up one row | | DF FF | -33 | Up-right diagonal | These offsets correspond to movement within the ZX81 display file, where each row is 33 bytes wide (32 character cells plus a `0x76` newline byte), explaining the +34/−34 and related values. ### Notable Anomalies - The trailing bytes `0x17` repeated 21 times at the very end of the REM are `RLA` (rotate left through carry) instructions. These appear to be padding or part of the RNG shift chain and would execute harmlessly if the PC ever reached them before a `RET` or jump. - Address `0x4034` referenced in the code (`2A 34 40` = `LD HL,(0x4034)`) is the ZX81 `FRAMES` system variable — a 16-bit frame counter incremented by the display interrupt — confirming the entropy-injection mechanism. ## Source Code ``` 1 REM \2A\34\40\22\32\40\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\E5\23\3E\08\BE\28\FA\3E\76\BE\28\F5\ED\5B\10\40\E5\A7\ED\52\E1\30\0F\CD\5A\41\FE\A7\38\04\3E\88\18\01\AF\77\18\DB\E1\11\27\00\19\22\3C\40\21\00\04\22\46\40\2A\3C\40\23\22\3C\40\22\40\40\36\34\21\22\00\22\44\40\2A\46\40\2B\7C\B5\20\FB\CD\46\0F\D0\00\00\2A\40\40\36\00\ED\5B\44\40\19\7E\FE\00\20\07\36\34\22\40\40\18\DC\CD\5A\41\E6\0E\C6\4A\6F\26\41\5E\23\56\ED\53\44\40\FD\CB\26\46\20\06\2A\34\40\22\32\40\18\CB\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\E0\FF\01\00\22\00\21\00\20\00\FF\FF\DE\FF\DF\FF\E5\2A\32\40\54\5D\29\29\19\29\29\29\19\22\32\40\7C\E1\C9\17\17\17\17\17\17\17\17\17\17\17\17\17\17\17\17\17\17\17\17\17 2 SLOW 3 RAND USR 16514 4 REM IF THE BALL APPEARS TO BE LOCKED IN A PATTERN PRESS "SHIFT". IT WILL INTRODUCE A NUMBER FROM THE FRAMES COUNTER INTO THE PSEUDO RANDOM NO. GENERATOR ROUTINE. 5 SAVE "1023%6" 6 LIST 2 ```