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 322A3838262C2A FCDFC 2CD2A A 11F 6C53E 68047CDF5 8AFD7C110F32A E40A7ED422249402A1040235E2356EB19223C40EB23223E40CDBB 27C85FEFA2010CD2A A 1 8 0118240CD6B B 1 1 0C92129 0FEF828B0ED5B3E402A3C40A7ED5238C3EB16 05E23223E40 6 3CB23CB1210FA21 01E191140403E 84FEDB012 66CCD3C412A4940E5D11B 1C4 0EDB0DD2146401120 0 6 636762BAFDDCB 0 61F77A7ED52DD2B10EF 61BCD3C41FD3548 68F20CCC3BA404E4E4E4E10FAD3FF2A C40CBFCCD92 2ED5F 1 1193EF5CDB5 22BCD92 2DBFEC9
1 INPUT M$
2 RUN USR VAL "16525"
3 GOTO VAL "2"
1 REM 39383D3E363A3F37FF 1 1 0FFFF 0 1FF 611C5 62E4E10FDD3FF2A C40CBFCCD92 2ED5F 1 1193EF5CDB5 22BCD92 2C1DBFE10DDCD29 2ED4B2540CDBD 7FE3020 5CD69 818C8FE2D20 82111 7CDFC 218BCFE2C20 8CDE2 8CD2A A18B0FE3C20 7213C403E7118 9FE3B20 9213E403E80AE771898CB7628 AFDBE40324040208C18 5ED5B3C40197EFDB63ECB7728 33A3F40323F40ED4B4140CDF5 83A3F40D73A4040 1 8 0218240EDB1C29340 E 7 93A414086E61F4F233A424086FE1138 520 1AFE61047ED434140CDF5 87EFE7620 1AF323F403E17D7C39340
2 GOTO USR U
3 GOTO 2
0 REM E7415943 0 5 6 7 8 92221201F A B C D E1D1C1B1A2C2D2E2F3049484746313233343544434241FCDECABDA996857DFF7D6F645D534A413E 53E37312E2924201EFF1E1B18161412 F E 5 E23 97EE1FDCB3C4628 3CD7B41FD363CFF772336 03420 B35FE 528 62BCD7B4118EECD9B412B30 77E2318E82A8240E5CDBB 2E5C1AF2C2811CDBD 7218740 124 0EDB128B8FD363C 0E1FE 42847FE262848FE272847FE 2281FFE 120 4 1 2 0C9E5218640FE2428 6FE2328 418 3343435E1CD994118B53E 5BE38 9CD8A41BE38FACD7B417E23562BCD9D41389ECD7B4118E4CD8A4118 3CD7B417EA7288D23562BCD9D4118852323EB2A8440A7ED52EBD02A8240C92B2BEB2A824037ED52EBD82A8440C93EFF16 13C5F2835 6 63A8640835FD3FFCDB34110F91520EFC94B 0 07E3E 43D20FD D20F54B 0AFDB 0323D403E 1DB 0FD863DE63FFE3D D20EBC9 6 6CDB34110FB1520F6C9
1 REM FC 5DE 6CA 7BD 8A9 996 A85 97D CFF 57D 96F B64 E5D E53104A1141143E17FF 43E143719311C2E1F2923242920291E33FF 51E2B1B32183816371446123D F55 E5EFF10 56CFF 83E204A225D1B7D146F 564 65D 76F 95D 87D14FF 3FF 2FF 3531A3E224A1F5D166F 764 55D 653 F4A C5320FF 553 A4A1353 73E1A4A 753 85D1BFF 27D 86F D5D 66F D5D 76F 67D14FF 27D 85D124A 953 F7D 5FF 27D 55D E4A C5310FF 2FF 14A C41 E3E134A F5D C53157D 95D1CFF 7 59053 153 153 353 153 353 153 253 153 153 153 153 253 153 153 253 153 253 153 253 153 153 153 153 153 253 353 153 253 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 153 253 153 253 253 153 153 253 153 153 153 153 153 153 153 153 153 153 153 253 153 153 153 253 153 153 253 25D 15D 15D 25D 25D 6 5CE
2 SAVE "%3"
3 GOTO USR VAL "16637"
0 REM 66 0 0 0 0 079 0 0 0 0 04442 116 04442B9B7A6B3 0 0A6B2B9 0 DAAB7B7B4B735CD2A ACDE2 8 1 5 011A040CD6B BCD29 2CD2A AED4B2540CDBD 7329040FE 52817CDE2 87B 1 3 0FE20C8FE21C8 CFE22C8FE 9C8 E 6C9FD3540FCF541 1 5 0119540CD6B B2A3C40CDA5 AE5 1 6 0119A40CD6B BE1CD1442223C40CD2042EFE534CD61 B 1 9 0C9CD11422323117140CD 342EFE434CDA7 EC9CD2A A3A9040FE 928 4FE222060CD1341C5CDF541C12A8E40FD3540FAA640CDEA 928 611 6 01918EFE523CD1442D1ED539340 1 6 0EDB0FD3540F255413A9040FE222811EFE518C4 234CD 942CD2542CDFD411812218940117140CD 342CD2542118940CD 04221924035AFFE2120 DCD1341C5EFE518C5 234C118 7FE202033CD13412191407E2334BEDAA54078B1CAA5402A934070237123117640EBCD1842ED539340EFE5C4 234CD 942CD2542CDFD41AF218240ED5B1040 1 C 0EDB0FE 120 62174 2CDFC 2 1 8 0C9218E40113C4018 6118340217640 1 5 0EDB0C921834011764018F22A104023117640 1 4 0EDB0AF12C9EFA0C4 234EFA2E4E5 FA4A4 4 4C533 0 218E5 F36A4A4 4 5C5 234C9
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.

