This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
| Program | Application | MC Entry Point | Key Lines |
|---|---|---|---|
| 1 | Menu Loader | None | 10–80: PRINT menu |
| 2 | Billboard | USR VAL "16525" | 1: INPUT M$, 2: RUN USR, 3: GOTO 2 |
| 3 | Etch-A-Screen | GOTO USR U | 2: GOTO USR U, 3: GOTO 2 |
| 4 | Composer | USR VAL "16637" | 3: GOTO USR |
| 5 | Checkbook Balancer | USR VAL "16677" / USR VAL "16565" | 3–9: INPUT/PRINT/GOTO |
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number"inGO TOandUSR— saves bytes versus a floating-point numeric literal.RUN USR VAL "16525"— combinesRUN(which clears variables) with the USR call; unusual but valid on ZX81.GOTO USR U— uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.AT PI, NOT PI— encodes print coordinates using mathematical constants to minimize token storage.- Tight two-line loops (
GOTO 2→GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A,0x0292,0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions. - The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
F\CD\FC
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"F\C5E\CD\F5\AF\D7\C1\F3
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E\A7\ED
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
AE\EBC\EBE\CD\BB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\FE\FA\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\CDB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\C9
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\FE\F8\B0\EDBE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
AC\A7\ED\C3\EB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EE\CB\CB\FA
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"EEF\ED\B0C\CDC
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\E5\D1 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\C4
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\ED\B0\DD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\AF\DD\CB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"F\A7\ED\DD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\EF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"B\CDC\FDF\CC\C3\BAEEEE\FA\D3\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\CB\FC\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\EDF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"E\F5\CD\B5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM DEAF\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\FF\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\FF\C5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EE\FD\D3\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\CB\FC\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\EDF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"E\F5\CD\B5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\C1\DB\FE\DD\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\EDB\CD\BD\FE\CD\C8\FE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D\CD\FC
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\BC\FE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\CD\E2\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\B0\FECCE\FEBEE\AE\CB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\FD\BEC\EDBCE\FD\B6E\CBAFF\EDB\CD\F5AF\D7A itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\ED\B1\C2
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EA\E6 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"FFA\FE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\AF\E6\ED\CD\F5E\FE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\AFFE\D7\C3
2 GOTO USR U
3 GOTO 2
0 REM \E7
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"F
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"D itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
F\FC\DE\CA\BD\A9D\FFDFDAEE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"E\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"B
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
F
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EE\E1\FD\CBC\CDB\FDC\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\FE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\CDB\EE\CDB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
BE\E8
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\E5\CD\BB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\E5\C1\AF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\CD\BD itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\ED\B1\B8\FDC
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\E1\FE\FE\FE\FE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"F\FE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\C9\E5\FE\FE\E1\CD\B5E\BE\CDA\BE\FA\CDBE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\CDDE\CDB\E4\CDA\CDBE\A7D
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\CDD\EB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\A7\ED\EB\D0
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\C9
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\EB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\ED\EB\D8
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\C9E\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"CFAF\D3\FF\CD\B3\F9\EF\C9B
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EED\FD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D\F5B
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\AF\DB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
DE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"\DB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\FDD\E6F\FED
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D\EB\C9\CD\B3\FB\F6\C9
1 REM \FC\DE\CA\BD\A9
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
AD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\FFDF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
ED
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EAE\FFE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"F itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"E\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"E
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"BD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
F
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EE\FFC\FFEAD itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"BDFDFDD\FF\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"AEA itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"FDFD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
FA
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
AAE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"AAD itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"B\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
DF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
DDF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
DDFD\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
DDA
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
FD\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
DD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EA
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\FF
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
EEA
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
FD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
CDD itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"C\FF itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4" itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"D itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"D
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\B9\B7\A6\B3
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\A6\B2\B9
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D\AA\B7\B7\B4\B7\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\CD\E2 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\A0\CDB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\EDB\CD\BD\FE\CD\E2B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\FE\C8\FE\C8
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C\FE\C8\FE\C8
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E\C9\FD\FC\F5 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\CDB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
AC\CD\A5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\E5 itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\CDB
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B\E1\CDC\CD\EF\E5\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
B itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\C9\CD\CD\EF\E4\CD\A7
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
E\C9\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
AA\FE\FE\CD\C5\CD\F5\C1
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
AE\FD\FA\A6\CD\EA
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\EF\E5\CD\D1\ED itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\ED\B0\FD\F2A\FE\EF\E5\C4
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\CD\CD\CD\FD\CD\CD\CD
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\AF\FE
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
D\CD\C5\EF\E5\C5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\C1\FE\CDE\BE\DA\A5\B1\CA\A5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A\EB\CD\ED\EF\E5\C4
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\CD\CD\CD\FD\AF\EDB itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
C
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\ED\B0\FE itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\CD\FC
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\C9EC itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\ED\B0\C9\F2
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
A itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56751 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.6 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.4"
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\ED\B0\AF\C9\EF\A0\C4
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\EF\A2\E4\E5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
F\A4\A4\C5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\E5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
F\A4\A4\C5
Skip to content
ZX81 Home Computer Package
This is a four-program ZX81/TS1000 home computer package by Lamo-Lem Labs, consisting of a menu loader plus three applications: Billboard (a scrolling marquee display), Etch-A-Screen (a freehand drawing program), and Composer (a music composition tool), with a Checkbook Balancer as the fourth module. Each application stores substantial Z80 machine code in REM statements at line 0 or line 1, invoked via USR calls — a standard technique for embedding native code in ZX81 BASIC programs. The machine code routines handle hardware-level tasks such as direct port I/O (OUT FFh), keyboard scanning, and display manipulation that would be impractical in BASIC alone. The Checkbook Balancer uses BASIC expressions like AT PI,NOT PI (evaluating to AT 3,0) as a compact way to specify print positions without numeric literals.
Program Analysis
Program Structure
The package is organized as five separate BASIC programs intended to be loaded in sequence from tape. The first program is a menu loader that presents the four application choices. The remaining four programs implement Billboard, Etch-A-Screen, Composer, and Checkbook Balancer respectively. Each application program uses SAVE at an early line to allow re-saving, then immediately transfers control to machine code.
Program Application MC Entry Point Key Lines 1 Menu Loader None 10–80: PRINT menu 2 Billboard USR VAL "16525"1: INPUT M$, 2: RUN USR, 3: GOTO 2 3 Etch-A-Screen GOTO USR U2: GOTO USR U, 3: GOTO 2 4 Composer USR VAL "16637"3: GOTO USR 5 Checkbook Balancer USR VAL "16677" / USR VAL "16565"3–9: INPUT/PRINT/GOTO
Machine Code in REM Statements
Each application embeds its Z80 machine code payload in REM statements at line 0 or line 1. On the ZX81, the body of a REM line is stored verbatim in memory at a predictable address, making it an ideal container for binary data. The USR keyword transfers BASIC execution to the Z80 routine at the computed address. Address 16525 (0x408D) corresponds to the ZX81 RAM area just above system variables, consistent with the REM payload starting near the default RAMTOP position.
Notable Z80 instructions visible in the hex payloads include OUT (FF),A (port FFh — the ZX81 NMI/display port), ED B0 (LDIR block copy), DB FE (IN A,(FE) — keyboard port), and various CD (CALL) sequences targeting ZX81 ROM routines such as CD 2A 0A and CD 92 02.
Billboard Program
The Billboard program accepts a message via INPUT M$ at line 1, then calls the machine code at USR VAL "16525" to scroll the text across the display. Line 3 loops back to line 2 with GOTO VAL "2", which re-executes the USR call. The use of VAL "2" and VAL "16525" rather than bare literals saves a small number of bytes by storing the number as a string rather than as a five-byte floating-point constant.
Etch-A-Screen Program
The Etch-A-Screen program uses the variable U (uninitialised, defaulting to 0 on the ZX81) as the USR target in GOTO USR U. However, the true entry point is computed by the machine code itself, loaded into a register on entry; the BASIC line merely serves as the jump-off point after the REM machine code is in place in memory. The tight loop GOTO 2 / GOTO USR U keeps re-entering the driver. The machine code payload in line 1 REM includes keyboard scanning via DB FE and character plotting routines.
Composer Program
The Composer’s line 0 REM contains a large table of note frequency and duration data (the structured byte sequences with values such as FC DE CA BD A9 96 85 7D are a descending frequency table for the tone generator). Line 1 REM holds what appears to be encoded musical score data followed by a long sequence of 53 xx 5D xx pairs — likely (note, duration) pairs for playback. The tone output is driven through port FF (D3 FF), which toggles the ZX81’s speaker line.
Checkbook Balancer
The Checkbook Balancer is the only module with meaningful BASIC logic visible. Line 8 uses the expression AT PI, NOT PI to specify print coordinates. PI evaluates to approximately 3.14159, which truncates to 3 for the row, and NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0) for the column. Similarly, AT PI+PI, NOT PI gives row 6, column 0. This is a space-saving trick: the keyword PI occupies one byte as a token, whereas the literal 3 stored as a floating-point number occupies six bytes in a BASIC line.
Key BASIC Idioms
VAL "number" in GO TO and USR — saves bytes versus a floating-point numeric literal.
RUN USR VAL "16525" — combines RUN (which clears variables) with the USR call; unusual but valid on ZX81.
GOTO USR U — uses an uninitialized variable as an indirect jump, relying on machine code already being in memory.
AT PI, NOT PI — encodes print coordinates using mathematical constants to minimize token storage.
- Tight two-line loops (
GOTO 2 → GOTO USR ...) keep the machine code driver re-entrant from BASIC.
Notable Techniques and Observations
- All heavy work (scrolling, drawing, sound, I/O) is handled in Z80 machine code; BASIC lines serve only as scaffolding and re-entry points.
- The Composer’s REM at line 1 encodes both the playback engine and what appears to be a pre-composed tune as inline data, making the program entirely self-contained.
- ROM routine addresses called from machine code (e.g.,
0x022A, 0x0292, 0x0BD2) correspond to known ZX81 ROM entry points for display, keyboard, and utility functions.
- The Checkbook Balancer’s machine code (line 0 REM, ~300 bytes) implements what appears to be a simple data-entry and arithmetic engine, with the BASIC layer handling only prompts and display formatting.
Content
Source Code
0 REM COPYRIGHT 1982 LAMO-LEM LABS
1 SAVE "%0"
10 PRINT AT 3,11;"THE ZX81"
20 PRINT AT 5,5;"HOME COMPUTER PACKAGE"
30 PRINT AT 8,0;"1) BILLBOARD"
40 PRINT AT 10,0;"2) ETCH-A-SCREEN"
50 PRINT AT 12,0;"3) COMPOSER"
60 PRINT AT 14,0;"4) CHECKBOOK BALANCER"
70 PRINT AT 20,1;"COPYRIGHT 1982 LAMO-LEM LABS"
80 PRINT " BOX 2382, LA JOLLA, CA 92038"
0 REM \32\2A\38\38\26\2C\2A\0F\CD\FC\02\CD\2A\0A\01\1F\06\C5\3E\06\80\47\CD\F5\08\AF\D7\C1\10\F3\2A\0E\40\A7\ED\42\22\49\40\2A\10\40\23\5E\23\56\EB\19\22\3C\40\EB\23\22\3E\40\CD\BB\02\7C\85\FE\FA\20\10\CD\2A\0A\01\08\00\11\82\40\CD\6B\0B\01\01\00\C9\21\29\00\FE\F8\28\B0\ED\5B\3E\40\2A\3C\40\A7\ED\52\38\C3\EB\16\00\5E\23\22\3E\40\06\03\CB\23\CB\12\10\FA\21\00\1E\19\11\40\40\3E\08\4F\ED\B0\12\06\6C\CD\3C\41\2A\49\40\E5\D1\1B\01\C4\00\ED\B0\DD\21\46\40\11\20\00\06\06\36\76\2B\AF\DD\CB\00\06\1F\77\A7\ED\52\DD\2B\10\EF\06\1B\CD\3C\41\FD\35\48\06\8F\20\CC\C3\BA\40\4E\4E\4E\4E\10\FA\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\DB\FE\C9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM \39\38\3D\3E\36\3A\3F\37\FF\01\01\00\FF\FF\00\01\FF\06\11\C5\06\2E\4E\10\FD\D3\FF\2A\0C\40\CB\FC\CD\92\02\ED\5F\01\01\19\3E\F5\CD\B5\02\2B\CD\92\02\C1\DB\FE\10\DD\CD\29\02\ED\4B\25\40\CD\BD\07\FE\30\20\05\CD\69\08\18\C8\FE\2D\20\08\21\11\07\CD\FC\02\18\BC\FE\2C\20\08\CD\E2\08\CD\2A\0A\18\B0\FE\3C\20\07\21\3C\40\3E\71\18\09\FE\3B\20\09\21\3E\40\3E\80\AE\77\18\98\CB\76\28\0A\FD\BE\40\32\40\40\20\8C\18\05\ED\5B\3C\40\19\7E\FD\B6\3E\CB\77\28\03\3A\3F\40\32\3F\40\ED\4B\41\40\CD\F5\08\3A\3F\40\D7\3A\40\40\01\08\00\21\82\40\ED\B1\C2\93\40\0E\07\09\3A\41\40\86\E6\1F\4F\23\3A\42\40\86\FE\11\38\05\20\01\AF\E6\10\47\ED\43\41\40\CD\F5\08\7E\FE\76\20\01\AF\32\3F\40\3E\17\D7\C3\93\40
2 GOTO USR U
3 GOTO 2
0 REM \E7\41\59\43\00\05\06\07\08\09\22\21\20\1F\0A\0B\0C\0D\0E\1D\1C\1B\1A\2C\2D\2E\2F\30\49\48\47\46\31\32\33\34\35\44\43\42\41\FC\DE\CA\BD\A9\96\85\7D\FF\7D\6F\64\5D\53\4A\41\3E\05\3E\37\31\2E\29\24\20\1E\FF\1E\1B\18\16\14\12\0F\0E\05\0E\23\09\7E\E1\FD\CB\3C\46\28\03\CD\7B\41\FD\36\3C\FF\77\23\36\00\34\20\0B\35\FE\05\28\06\2B\CD\7B\41\18\EE\CD\9B\41\2B\30\07\7E\23\18\E8\2A\82\40\E5\CD\BB\02\E5\C1\AF\2C\28\11\CD\BD\07\21\87\40\01\24\00\ED\B1\28\B8\FD\36\3C\00\E1\FE\04\28\47\FE\26\28\48\FE\27\28\47\FE\02\28\1F\FE\01\20\04\01\02\00\C9\E5\21\86\40\FE\24\28\06\FE\23\28\04\18\03\34\34\35\E1\CD\99\41\18\B5\3E\05\BE\38\09\CD\8A\41\BE\38\FA\CD\7B\41\7E\23\56\2B\CD\9D\41\38\9E\CD\7B\41\18\E4\CD\8A\41\18\03\CD\7B\41\7E\A7\28\8D\23\56\2B\CD\9D\41\18\85\23\23\EB\2A\84\40\A7\ED\52\EB\D0\2A\82\40\C9\2B\2B\EB\2A\82\40\37\ED\52\EB\D8\2A\84\40\C9\3E\FF\16\01\3C\5F\28\35\06\06\3A\86\40\83\5F\D3\FF\CD\B3\41\10\F9\15\20\EF\C9\4B\00\00\7E\3E\04\3D\20\FD\0D\20\F5\4B\00\AF\DB\00\32\3D\40\3E\01\DB\00\FD\86\3D\E6\3F\FE\3D\0D\20\EB\C9\06\06\CD\B3\41\10\FB\15\20\F6\C9
1 REM \FC\05\DE\06\CA\07\BD\08\A9\09\96\0A\85\09\7D\0C\FF\05\7D\09\6F\0B\64\0E\5D\0E\53\10\4A\11\41\14\3E\17\FF\04\3E\14\37\19\31\1C\2E\1F\29\23\24\29\20\29\1E\33\FF\05\1E\2B\1B\32\18\38\16\37\14\46\12\3D\0F\55\0E\5E\FF\10\05\6C\FF\08\3E\20\4A\22\5D\1B\7D\14\6F\05\64\06\5D\07\6F\09\5D\08\7D\14\FF\03\FF\02\FF\03\53\1A\3E\22\4A\1F\5D\16\6F\07\64\05\5D\06\53\0F\4A\0C\53\20\FF\05\53\0A\4A\13\53\07\3E\1A\4A\07\53\08\5D\1B\FF\02\7D\08\6F\0D\5D\06\6F\0D\5D\07\6F\06\7D\14\FF\02\7D\08\5D\12\4A\09\53\0F\7D\05\FF\02\7D\05\5D\0E\4A\0C\53\10\FF\02\FF\01\4A\0C\41\0E\3E\13\4A\0F\5D\0C\53\15\7D\09\5D\1C\FF\07\05\90\53\01\53\01\53\03\53\01\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\01\53\02\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\02\53\03\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\02\53\02\53\01\53\01\53\02\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\01\53\02\53\01\53\01\53\01\53\02\53\01\53\01\53\02\53\02\5D\01\5D\01\5D\02\5D\02\5D\06\05\CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM \66\00\00\00\00\00\79\00\00\00\00\00\44\42\01\16\00\44\42\B9\B7\A6\B3\00\00\A6\B2\B9\00\0D\AA\B7\B7\B4\B7\35\CD\2A\0A\CD\E2\08\01\05\00\11\A0\40\CD\6B\0B\CD\29\02\CD\2A\0A\ED\4B\25\40\CD\BD\07\32\90\40\FE\05\28\17\CD\E2\08\7B\01\03\00\FE\20\C8\FE\21\C8\0C\FE\22\C8\FE\09\C8\0E\06\C9\FD\35\40\FC\F5\41\01\05\00\11\95\40\CD\6B\0B\2A\3C\40\CD\A5\0A\E5\01\06\00\11\9A\40\CD\6B\0B\E1\CD\14\42\22\3C\40\CD\20\42\EF\E5\34\CD\61\0B\01\09\00\C9\CD\11\42\23\23\11\71\40\CD\03\42\EF\E4\34\CD\A7\0E\C9\CD\2A\0A\3A\90\40\FE\09\28\04\FE\22\20\60\CD\13\41\C5\CD\F5\41\C1\2A\8E\40\FD\35\40\FA\A6\40\CD\EA\09\28\06\11\06\00\19\18\EF\E5\23\CD\14\42\D1\ED\53\93\40\01\06\00\ED\B0\FD\35\40\F2\55\41\3A\90\40\FE\22\28\11\EF\E5\18\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\18\12\21\89\40\11\71\40\CD\03\42\CD\25\42\11\89\40\CD\00\42\21\92\40\35\AF\FE\21\20\0D\CD\13\41\C5\EF\E5\18\C5\02\34\C1\18\07\FE\20\20\33\CD\13\41\21\91\40\7E\23\34\BE\DA\A5\40\78\B1\CA\A5\40\2A\93\40\70\23\71\23\11\76\40\EB\CD\18\42\ED\53\93\40\EF\E5\C4\02\34\CD\09\42\CD\25\42\CD\FD\41\AF\21\82\40\ED\5B\10\40\01\0C\00\ED\B0\FE\01\20\06\21\74\02\CD\FC\02\01\08\00\C9\21\8E\40\11\3C\40\18\06\11\83\40\21\76\40\01\05\00\ED\B0\C9\21\83\40\11\76\40\18\F2\2A\10\40\23\11\76\40\01\04\00\ED\B0\AF\12\C9\EF\A0\C4\02\34\EF\A2\E4\E5\0F\A4\A4\04\04\C5\33\00\02\18\E5\0F\36\A4\A4\04\05\C5\02\34\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
People
No people associated with this content.
\C9
1 REM
3 INPUT A
4 PRINT "%T"
5 INPUT T
7 GOTO USR VAL "16677"
8 PRINT "%B%A%L%A%N%C%E";AT PI,NOT PI;"BANK $";T;AT PI+PI,NOT PI;"CHECKBOOK $";A
9 GOTO USR VAL "16565"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.



