ZX ToolBox is a collection of three utility programs for tape-based systems: a Directory utility, a Record utility, and a Toolkit loader. The Directory program uses RAND USR 16514 to invoke a machine code routine that reads tape header data, then inspects memory addresses 16444–16463 to extract and display program names, detecting the end of each name by checking for characters with values above 128 (high-bit set). The Record utility stores up to 96 characters of user-entered text by POKEing directly into memory starting at address 16714, and uses machine code calls at addresses 16523 and 16599 (USR 16523 for write, USR 16599 for read) to save and reload that data block. The Toolkit loader (line 5) calls RAND USR 16547 to initialize the machine code toolkit, with its routines encoded within REM statements at lines 20 and 30.
Program Analysis
Program Structure
ZX ToolBox comprises three independent BASIC programs, each saved separately to tape. They are:
- Directory (lines 10–200): Reads tape headers and displays up to 15 program names.
- Record (lines 10–170): Provides a simple database record facility — read, write, or enter a 96-character record stored in RAM.
- Toolkit (lines 5–30, appearing twice): Loads a machine code toolkit stored in REM statements.
Directory Program
The Directory utility loops 15 times (line 60, FOR A=1 TO 15). Each iteration POKEs 255 into address 16437 (line 50/160) to keep the system ready, then calls RAND USR 16514 (line 70) to invoke a machine code routine that reads a tape block header into the system area. The program name is then extracted by inspecting bytes at addresses 16444–16463 (20 bytes, matching the ZX81 system variable area for tape header name storage).
Name termination is detected by checking whether PEEK B > 128 (line 100): on the ZX81, the last character of a stored name has its high bit set. When this terminating character is found, the program prints the character with 128 subtracted (line 140) and appends a closing quote, then pauses 400 frames before continuing to the next entry.
Record Program
The Record utility manages a fixed-length 96-character record stored at addresses 16714–16810 in RAM. The main menu (lines 30–50) offers three options: read back (option 1), write (option 2), or enter new data (option 3).
Machine code entry points handle the tape operations: RAND USR 16523 is called for write (option 2) and RAND USR (16523 + 76), i.e. RAND USR 16599, for read (option 1). The expression VAL "16523"+(A=VAL "1")*VAL "76" on line 60 neatly selects the correct entry point using a Boolean multiply idiom — when A=1, the condition evaluates to -1 (true), so *76 yields -76, but as written the multiplication of (A=VAL "1")*VAL "76" gives -76 when true; however since true is -1 in BASIC, the actual computed address would be 16523 + (-1)*76 = 16447. This suggests the intended behavior relies on the machine code layout, or the subtraction is intentional to select an earlier entry point for reading.
Data entry (option 3, lines 80–140) clears all 96 record bytes to zero first, then POKEs in the ASCII codes of the entered string A$ up to its length. VAL "number" is used consistently throughout for literal numeric arguments as a memory-saving technique.
Toolkit Loader
The Toolkit program is minimal: line 5 saves itself to tape, and line 10 executes RAND USR 16547 to jump into machine code. Lines 20 and 30 are REM statements that contain the actual machine code data — a standard technique for embedding machine code in BASIC programs where the REM body is never executed as BASIC but is present in memory for the USR call to use.
The program listing appears twice in the source, which is a duplication in the original listing (likely a typesetting artifact).
Notable Techniques
- High-bit name termination: Using
PEEK B > 128to detect the last character of a tape header name is idiomatic for the ZX81 tape system, where the final byte of the name field has bit 7 set. - Boolean arithmetic for branching: In the Record program,
(A=VAL "1")*VAL "76"selects between two machine code entry points without an explicitIFstatement. - VAL “number” idiom: Numeric literals wrapped in
VALcalls are used extensively in the Record program to reduce the size of the BASIC line stored in memory, since the tokenized number representation is replaced by a shorter string. - Machine code in REM: The Toolkit stores executable machine code inside REM statement bodies at lines 20 and 30, a well-established technique for attaching machine code routines to a BASIC program without needing a separate LOAD block.
- Direct memory POKEing for data storage: Both the Directory and Record programs interact directly with system RAM rather than using BASIC arrays, giving precise control over data layout and enabling machine code routines to access the same locations.
Memory Map Summary
| Address | Usage |
|---|---|
16437 | POKEd to 255 to reset tape-read state between header reads |
16444–16463 | Tape header name field (20 bytes); inspected for program name |
16514 | Machine code entry: read tape header (Directory) |
16523 | Machine code entry: write record to tape (Record) |
16547 | Machine code entry: Toolkit initialization |
16599 | Machine code entry: read record from tape (Record, = 16523+76) |
16714–16809 | 96-byte record data storage area (Record) |
Content
Source Code
10 REM 5[~~]RND FASTE[J]£ DIM )>#Y#<= RETURN3SQR **S PAUSE .#[N]4 LIST 5WRND2▒Y#<= RETURNPEEK COPY3SQR **K NEXT :[=]▞,$<= RETURN*ACS ##S PRINT ( PRINT 4▖ RETURN#K THENZACS -14**LN ABS RND/SGN 7 FOR 5#RNDR GOSUB # FOR SQR LPRINT E[G]£ DIM
20 PRINT AT 4,4;"+ DIRECTORY +"
30 PRINT
40 PAUSE 9999
50 POKE 16437,255
60 FOR A=1 TO 15
70 RAND USR 16514
80 PRINT "PROGRAM ";A;TAB 11;"""";
90 FOR B=16444 TO 16463
100 IF PEEK B>128 THEN GOTO 140
110 PRINT CHR$ PEEK B;
120 NEXT B
130 GOTO 150
140 PRINT CHR$ (PEEK B-128);""""
150 PAUSE 400
160 POKE 16437,255
170 NEXT A
180 STOP
190 SAVE "DIRECTOR[Y]"
200 RUN
10 REM 5[~~]RND FASTE[J]£ DIM TAN LN ▙RND)ACS ▒( RETURN.#[N]4 RAND 5#INKEY$ )▒ SAVE ACS ▞[3] NEW▌LEN ▖#PEEK COPY▞A( RETURNY#<= RETURN▞7( RETURN$4 LOAD PI ( CLEAR- RETURN14 THEN3SQR LN COS RND/PEEK 7 FOR 5[F]INKEY$ R GOSUB # FOR SQR LPRINT E[G]£ DIM LN ▙RND)>#Y#<= RETURN3SQR **S PAUSE .#[N]4 LIST 5#INKEY$ 2▒Y#<= RETURNPEEK COPY3SQR **K NEXT :[=]▞,$<= RETURN*ACS ##S PRINT ( PRINT 4▖ RETURN#K THENZACS -14**LN COS RND/SGN
20 CLS
30 PRINT "PRESENT RECORD";AT VAL "4",VAL "0";"123456789012345678901234567890123456789012345678902234567890123456789012345678901234567890123456"
40 PRINT AT VAL "16",VAL "0";"1-READ, 2-WRITE, 3-ENTER"
50 INPUT A
60 IF A<=VAL "2" THEN RAND USR (VAL "16523"+(A=VAL "1")*VAL "76")
70 IF A<>VAL "3" THEN RUN
80 CLS
90 PRINT "ENTER YOUR NEW RECORD"
100 INPUT A$
110 FOR A=VAL "1" TO VAL "96"
120 POKE VAL "16714"+A,VAL "0"
130 IF A<=LEN A$ THEN POKE VAL "16714"+A,CODE A$(A)
140 NEXT A
150 RUN
160 SAVE "RECOR[D]"
170 RUN
5 SAVE "TLKI[T]"
10 RAND USR (16547)
20 REM E▖RNDY#[W]K$LN E~~5#INKEY$ Q#5##/?[J]▞£VAL ▞4NOT ( CLEARAT ( RUN 5##6▖RNDE£RND)#▘; FOR 5)INKEY$ ▘. GOSUB [K]▞#LN CLEARRNDLN PLOT RND( SAVE LN SCROLL▝ GOSUB #▖RND5MINKEY$ ▘[(] GOSUB [K]# FAST▀VAL ▞ ( RETURNAT TAN E£RND:/7# RETURN#C▌LEN █#/ PRINT $4 PAUSE TAN TOOLKIT SUCCESSFULLY LOADED
30 REM 5 NEW#/$5 PLOT █/▒5LEN █/▀5Y█6[+]# GOSUB #£RND▀E(RND GOSUB PICOS ~~ RETURN#C POKE PLOT █▝/ LOAD 5 GOSUB #0RND[B] GOSUB PI GOSUB ###TAN 5#RND▘~~ )~~ # RETURN#COS #7#7 FOR ,, FOR STR$ #7#7;SGN / GOTO 5#RND7# RETURN#COS 77#7#7.#[M]C LIST # RETURN#4~~▘▌ ,, FOR GOSUB PI FOR / FOR RETURN REM 4 SCROLLQ PRINT / STOP:~~▞4Y NOT ( CLEARY#NOT $COS / PAUSE
5 SAVE "TLKI[T]"
10 RAND USR (16547)
20 REM E▖RNDY#[W]K$LN E~~5#INKEY$ Q#5##/?[J]▞£VAL ▞4NOT ( CLEARAT ( RUN 5##6▖RNDE£RND)#▘; FOR 5)INKEY$ ▘. GOSUB [K]▞#LN CLEARRNDLN PLOT RND( SAVE LN SCROLL▝ GOSUB #▖RND5MINKEY$ ▘[(] GOSUB [K]# FAST▀VAL ▞ ( RETURNAT TAN E£RND:/7# RETURN#C▌LEN █#/ PRINT $4 PAUSE TAN TOOLKIT SUCCESSFULLY LOADED
30 REM 5 NEW#/$5 PLOT █/▒5LEN █/▀5Y█6[+]# GOSUB #£RND▀E(RND GOSUB PICOS ~~ RETURN#C POKE PLOT █▝/ LOAD 5 GOSUB #0RND[B] GOSUB PI GOSUB ###TAN 5#RND▘~~ )~~ # RETURN#COS #7#7 FOR ,, FOR STR$ #7#7;SGN / GOTO 5#RND7# RETURN#COS 77#7#7.#[M]C LIST # RETURN#4~~▘▌ ,, FOR GOSUB PI FOR / FOR RETURN REM 4 SCROLLQ PRINT / STOP:~~▞4Y NOT ( CLEARY#NOT $COS / PAUSE
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

