ZX ToolBox

Products: ZX Toolbox
Date: 1983
Type: Program
Platform(s): TS 1000
Tags: Utility

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:

  1. Directory (lines 10–200): Reads tape headers and displays up to 15 program names.
  2. Record (lines 10–170): Provides a simple database record facility — read, write, or enter a 96-character record stored in RAM.
  3. 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 > 128 to 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 explicit IF statement.
  • VAL “number” idiom: Numeric literals wrapped in VAL calls 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

AddressUsage
16437POKEd to 255 to reset tape-read state between header reads
16444–16463Tape header name field (20 bytes); inspected for program name
16514Machine code entry: read tape header (Directory)
16523Machine code entry: write record to tape (Record)
16547Machine code entry: Toolkit initialization
16599Machine code entry: read record from tape (Record, = 16523+76)
16714–1680996-byte record data storage area (Record)

Content

Appears On

Related Products

Three utility programs. Directory displays names of programs on a tape. Record allows SAVEing data and READing it back into...

Related Articles

Related Content

Image Gallery

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.

People

No people associated with this content.

Scroll to Top