--- title: "Z-AID" id: 56747 type: "computer_media" slug: "z-aid" url: "http://localhost/computer_media/z-aid/" markdown_url: "http://localhost/computer_media/z-aid.md" published_at: "2024-09-22T23:31:59+00:00" modified_at: "2026-04-04T20:17:47+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A self-installing machine code utility that decodes a Z80 hex payload from a BASIC string to supercharge cassette tape operations with verify, chain, and block save/load." 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: "International Publishing & Software Inc" slug: "international-publishing-software-inc" taxonomy: "post_tag" url: "http://localhost/tag/international-publishing-software-inc/" - 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: "Tape" slug: "tape" taxonomy: "genre" url: "http://localhost/type/tape/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Z-AID%20%281982%29%28International%20Publishing%20and%20Software%29%28TS1000%29%28US%29%28Cassette%29.zip" mediadate: "1982" producer_company: - id: 10960 title: "International Publishing & Software Inc" type: "company" url: "http://localhost/company/international-publishing-software-inc/" related_products: - id: 14653 title: "Z-AID" type: "product" url: "http://localhost/product/z-aid/" media_type_tags: "Tape" --- # Z-AID Z-AID is a utility that extends cassette tape operations by adding verify, chain, and block memory save/load capabilities through an embedded machine code routine. The program self-installs by decoding a hex string stored in Z$ (line 60) into raw Z80 machine code bytes at memory address 29000, using a FOR loop that processes the string two characters at a time. Each byte value is reconstructed by subtracting 28 from each character code and combining the two nibbles — an encoding scheme that keeps all characters printable on the ZX81 character set. After decoding, control is transferred to the routine via RAND USR 29000. The startup sequence uses SLOW mode, displays a title screen, and prompts the user to position the tape before the load sequence begins at line 9. *** ## Program Analysis ### Program Structure The program has two distinct execution paths controlled by the entry point. Line 5 jumps immediately to line 18, which runs the interactive title/setup sequence. Lines 9–17 form the tape-load completion handler, reached via `GOTO 9` at line 80 after the machine code has been POKEd into memory. The overall flow is: 1. Line 5: `GOTO 18` — skip the load-complete handler on first run. 2. Lines 18–55: Display title screen in SLOW mode, prompt user to stop the tape latch. 3. Lines 55–80: Initialize target address `T=29000`, set up hex string `Z$`, `CLEAR 3000` to protect RAM from 3000 upward, then `GOTO 9`. 4. Lines 9–17: CLS, print restart-tape prompt, `PAUSE 100`, `RAND USR 29000` to execute the installed routine, then display load-complete message and `STOP`. 5. Lines 3000–8000: Subroutine that decodes `Z$` two characters at a time and POKEs bytes to address `T`. 6. Lines 9000–9010: `SAVE` then `RUN` — the distribution/re-save block. Note that the decode subroutine at lines 3000–8000 is never explicitly called with `GO SUB` in the visible listing; `CLEAR 3000` at line 62 protects the subroutine area, and the flow from line 80 goes to line 9 rather than into the subroutine directly. The subroutine ends with `RETURN` at line 8000, suggesting it was designed to be called via `GO SUB 3000` from a line that may have been removed or is reached differently in the saved version. ### Machine Code Encoding Scheme The hex payload in `Z$` (line 60) is not stored as ASCII hex digits. Instead, each nibble is offset by 28 added to its value, placing all characters in the printable ZX81 range. The decode loop at lines 3000–8000 reverses this: - Take two consecutive characters from `Z$`. - High nibble: `(CODE Z$(X) - 28) * 16` - Low nibble: `CODE Z$(X+1) - 28` - Sum the two to reconstruct the full byte, then `POKE T, V`. This encoding ensures the string contains no characters with codes below 28, avoiding control characters that would be illegal or ambiguous inside a ZX81 string literal. ### Z80 Payload Analysis The hex string in `Z$` decodes to approximately 50 bytes of Z80 machine code installed at address 29000 (0x7148). Key opcodes visible in the raw hex include `CD` (CALL), `C9` (RET), `DB FE` (IN A,(254) — keyboard read), `D3 FF` (OUT (255),A — likely display or border), and loop constructs using `10` (DJNZ) and `20` (JR NZ). The routine is invoked via `RAND USR 29000`, which is the standard ZX81 idiom for calling machine code from BASIC. ### Memory Layout | Address | Purpose | | --- | --- | | 3000 | CLEAR boundary — BASIC decode subroutine starts here (protected from BASIC memory manager) | | 29000 (0x7148) | Target address for decoded Z80 machine code; initial value of `T` | ### Key BASIC Idioms - `RAND USR 29000` — standard ZX81 technique to call a machine code address from BASIC without using `USR` in an expression context. - `CLEAR 3000` — reserves high memory for the machine code while also resetting the stack; used here to protect the subroutine lines from being overwritten. - `FOR X=1 TO LEN Z$ STEP 2` — iterates over pairs of characters in the encoded string without hardcoding the byte count, making the routine length-agnostic. - The `SAVE "[B]"` at line 9000 followed immediately by `RUN` at line 9010 is the standard self-replicating distribution pattern for ZX81 utilities. ### Anomalies and Notable Points - The decode subroutine (lines 3000–8000) ends with `RETURN`, implying a `GO SUB 3000` call that is not present in the listed code between lines 62 and 80. It is likely that a `GO SUB 3000` was intended between lines 62 and 80 and is missing from the listing, or the `GOTO 9` at line 80 was meant to be `GO SUB 3000: GOTO 9`. - Lines 25, 38, and 48 contain copyright and publisher text printed in plain (non-inverse) characters, consistent with a commercial product splash screen. - The `PAUSE 100` at line 11 gives the user roughly 5 seconds to act on the “PLEASE RESTART THE TAPE NOW” prompt before `RAND USR 29000` executes the installed utility. ## Source Code ``` 5 GOTO 18 9 CLS 10 PRINT AT 10,1;"[P][L][E][A][S][E]█[R][E][S][T][A][R][T]█[T][H][E]█[T][A][P][E]█[N][O][W]" 11 PAUSE 100 12 RAND USR 29000 15 CLS 16 PRINT AT 10,3;"[Z][-][A][I][D]█[L][O][A][D]█[I][S]█[N][O][W]█[C][O][M][P][L][E][T][E]" 17 STOP 18 SLOW 19 CLS 20 PRINT AT 4,7;"[Z][-][A][I][D]█[1][.][0]" 25 PRINT AT 6,0;"COPYRIGHT 1982 BY" 38 PRINT AT 7,0;"INTERNATIONAL PUBLISHING ";AT 8,0;"AND SOFTWARE INC." 48 PRINT AT 10,0;"[*][*]██[P][R][E][S][S]█[T][H][E]█[S][T][O][P]█[L][A][T][C][H]██████[*][*][*][*]████[O][N]█[T][H][E]█[T][A][P][E]█[D][E][C][K]████████[*][*]" 55 LET T=29000 60 LET Z$="CD[3]30#260FCD72712520FACD727169CD727161CD7271C5CD727179C147C5CD72717123C10B78B120F4C90E0106003E7FDBFED3FF1FD2A2031717380510F0C372711E94061A1DDBFE17CB7B7B38F510F52004FE5630D63FCB1130D1C9" 62 CLEAR3000 80 GOTO 9 3000 FOR X=1 TO LEN Z$ STEP 2 4000 LET V=(CODE Z$(X)-28)*16+CODE Z$(X+1)-28 5000 POKE T,V 6000 LET T=T+1 7000 NEXT X 8000 RETURN 9000 SAVE "[B]" 9010 RUN ```