This program is the documentation and menu handler for “TOOLKIT,” a BASIC utility suite for the TS2068 (adapted from a Spectrum original by John Charlesworth, published in Your Computer Vol. 4, No. 4). The toolkit provides four machine code routines: a BASIC line renumberer, a REM statement killer, a variable lister, and a BASIC compactor that converts numeric literals to VAL “n” form to save 3 bytes per number. The machine code block is 1350 bytes long, loaded at address 64048, with entry points at 64048 (renumber), 64841 (REMKILL), 65017 (compaction), and 65184 (list variables). The renumber routine reads its new-first-line and step values from system memory via POKE to addresses 23299–23302 before calling USR 64048. A two-part tape SAVE routine stores the BASIC and machine code separately, and the loader at line 9998 uses CLEAR to set RAMTOP before loading the code block.
Program Analysis
Program Structure
The program is divided into two major functional blocks: a documentation browser (lines 9936–9987) and the main toolkit menu/dispatcher (lines 9988–9999). The documentation block itself is organized as a multi-page reader with a shared subroutine-like jump target at line 9980 that handles page-turn navigation. The toolkit menu at line 9988 uses a numeric INPUT into variable FFF to select functions, followed by a cascade of IF statements dispatching to the appropriate machine code entry point.
Documentation Browser (Lines 9936–9985)
Lines 9936–9945 display the top-level documentation menu and handle key input for four choices: backup, read documentation, go to toolkit menu, or stop. The documentation itself spans six pages (lines 9947–9976), each page ending with a LET RET=VAL "NNNN": GO TO VAL "9980" pattern that stores a return address in the variable RET before jumping to the shared page-navigation handler.
The handler at line 9980 prints a status bar to channel #1 (the lower screen) offering COPY, MENU, or ENTER=NEXT PAGE options. Lines 9981–9985 poll INKEY$ in a tight loop, branching on Enter (CHR$ 13) to clear screen and jump to RET, on M/m to RUN (restarting the program), or on C/c to invoke COPY.
Toolkit Menu and Dispatcher (Lines 9988–9997)
Line 9988 presents the six-option main menu and takes a numeric INPUT into FFF. Option 1 (RENUMBER) falls through to line 9989, which prompts for the new first line number (TTT, default 100) and step (SSS, default 10). Line 9990 validates the parameters before proceeding.
Options 2 through 5 are handled by individual IF lines (9992–9995), each calling a specific machine code entry point via RANDOMIZE USR or PRINT USR.
Machine Code Entry Points
| Option | Function | Entry Point | Call Method |
|---|---|---|---|
| 1 | Renumber | 64048 | RANDOMIZE USR |
| 2 | REMKILL | 64841 | RANDOMIZE USR |
| 3 | List Variables | 65184 | PRINT USR |
| 4 | Compaction | 65017 | RANDOMIZE USR |
The use of PRINT USR for the variable lister (line 9993) rather than RANDOMIZE USR is intentional: the machine code routine returns a value to be printed, or the call is simply used for its side effect with the return value discarded to screen. Note that line 9993 issues a STOP after the call, consistent with the documentation’s instruction to use COPY to capture variable output.
Renumber Parameter Passing via POKE
Line 9991 communicates the new first line and step to the machine code by POKEing values into addresses 23299–23302. The high and low bytes of each 16-bit value are computed manually:
POKE 23300, INT(TTT/256)— high byte of new first linePOKE 23299, TTT - 256*PEEK 23300— low byte of new first linePOKE 23302, INT(SSS/256)— high byte of stepPOKE 23301, SSS - 256*PEEK 23302— low byte of step
This avoids using the INT/MOD combination or bitwise operations, instead reading back the already-POKEd high byte to compute the low byte remainder.
SAVE/LOAD Mechanism (Lines 9946, 9995, 9998–9999)
The program performs a two-part tape operation: first saving the BASIC with LINE 9998 as the auto-start line, then saving the 1350-byte machine code block starting at address 64048. Line 9998 is the bootstrap loader that issues CLEAR 64048 to set RAMTOP, prints a status message, and then loads the code block. Line 9999 jumps to line 9931, which is not present in this listing — it presumably exists in the full loaded program as an entry point into the toolkit.
The backup option at line 9946 saves under the name “TOOLKIT” whereas the in-menu save at line 9995 uses “TK” and “TKB” — a minor inconsistency between the two save paths.
Key BASIC Idioms and Techniques
- VAL “n” everywhere: Nearly all numeric literals are written as
VAL "n", which is the compaction format that TOOLKIT’s own compaction function produces. This entire handler section is already in compacted form, demonstrating the tool’s output. - Tight INKEY$ polling: Lines like
IF INKEY$="" THEN GO TO VAL "9939"form a busy-wait loop for key detection, a standard idiom. - Lower-screen status bar:
PRINT #VAL "1"; AT VAL "0", VAL "0"; ...writes to the two-line lower screen area (stream 1), keeping menu prompts separate from the main display area. - GO TO non-existent line 9931: Used deliberately as a jump to a line that exists only after the full toolkit is loaded; harmless during documentation browsing since this path is only reached after a SAVE/LOAD cycle.
Anomalies and Notes
- Line 9952, 9958, 9964, 9970, 9975, 9978, 9979, 9986, and 9987 are empty lines serving only as visual separators in the listing.
- Line 9988 contains an
INPUT FFFfollowed immediately byIF FFF<>VAL "1" THEN GO TO VAL "9992", meaning option 1 falls through inline to line 9989 rather than branching — a slightly unusual but valid flow. - The documentation explicitly warns that
GO TO VAL "1000"-style computed line numbers will not be renumbered by the toolkit — an honest self-referential limitation, since this entire program uses that very pattern. - Line 9962 notes that a “NONSENSE IN BASIC” error after toolkit operations is not abnormal, suggesting the machine code may leave the BASIC pointer in an inconsistent state.
Content
Source Code
9936 BORDER VAL "1": PAPER VAL "1": INK VAL "6": CLS : PRINT " **TOOLKIT DOCUMENTATION MENU**"
9937 PRINT ''"1. BACKUP"''"2. READ DOCUMENTATION"''"3. GO TO TOOLKIT MENU"''"4. STOP"
9938 PRINT #VAL "1";AT VAL "0",VAL "5";"**PLEASE PRESS A KEY**"
9939 IF INKEY$="" THEN GO TO VAL "9939"
9940 LET K$=INKEY$
9941 IF K$="1" THEN GO TO VAL "9946"
9942 IF K$="2" THEN GO TO VAL "9947"
9943 IF K$="3" THEN GO TO VAL "9988"
9944 IF K$="4" THEN PRINT AT VAL "20",VAL "11";" OK TO RUN ": STOP
9945 GO TO VAL "9939"
9946 SAVE "TOOLKIT" LINE VAL "9998": SAVE "TOOLKIT"CODE VAL "64048",VAL "1350": GO TO VAL "9931"
9947 CLS : PRINT "** TOOLKIT DOCUMENTATION **"
9948 PRINT '"TOOLKIT has 4 main functions:"''"1) RENUMBER the BASIC program"''"2) KILL all REM statements"''"3) LIST all VARIABLES used"''"4) COMPACT the BASIC program"''"Each will be discussed in turn."
9949 PRINT '"TOOLKIT also has a BACKUP"'"function, which should be used"'"before other functions."
9950 PRINT '"TOOLKIT can be used with your"'"own BASIC programs. See Page 5."
9951 LET RET=VAL "9953": GO TO VAL "9980"
9952
9953 PRINT TAB VAL "10";"PAGE 2"''"RENUMBER renumbers all BASIC"'"lines, including TOOLKIT's Basic"'"Handler, lines 9988-9999."
9954 PRINT '"You get to specify the NEW FIRST"'"LINE(e.g.100) and STEP(e.g.10)."
9955 PRINT '"Line numbers following GOTO,"'"GOSUB, RUN, LIST, LLIST and"'"RESTORE are renumbered, with"'"the following limitations:"'" 1) No computed line numbers"'" 2) No nonexistent line numbers"
9956 PRINT '"Line numbers specified by other"'"kinds of statements are NOT"'"renumbered...such as"'" SAVE ""TK"" LINE 9998."
9957 LET RET=VAL "9959": GO TO VAL "9980"
9958
9959 PRINT TAB VAL "10";"PAGE 3"''"Also, line numbers of the form"'" GO TO VAL ""1000"""'"will NOT be renumbered."
9960 PRINT '"Any statements containing"'"computed or eVALuated line"'"numbers should be deleted prior"'"to renumbering. They can be re-"'"entered afterwards."
9961 PRINT '"Other kinds of statements"'"specifying line numbers will"'"be ignored, and should be"'"fixed after renumbering."
9962 PRINT '"NOTE: a NONSENSE IN BASIC"'"message following use of a TOOL-"'"KIT function is not abnormal."
9963 LET RET=VAL "9965": GO TO VAL "9980"
9964
9965 PRINT TAB VAL "10";"PAGE 4"''"REMKILL simply deletes all"'"statements beginning with a"'"REM statement."
9966 PRINT '"LIST VARIABLES does just that..."'"on the screen only. Use COPY to"'"get them on paper."
9967 PRINT '"COMPACTION changes all numbers"'"in the BASIC program to the form"'"VAL ""n"". This saves 3 bytes"'"per number."'"NOTE: RENUMBER BEFORE COMPACTION"
9968 PRINT ''"TOOLKIT's machine code is 1350"'"bytes long, starting at Location"'"64048. Entry points can be"'"discovered in the BASIC handler."
9969 LET ret=VAL "9971": GO TO VAL "9980"
9970
9971 PRINT TAB VAL "10";"PAGE 5"''"USING TOOLKIT WITH YOUR OWN"'"BASIC PROGRAM:"
9972 PRINT '"First, make sure your BASIC"'"program does not have any lines"'"numbered from 9988 to 9999."''"Then load TOOLKIT, STOP and"'"DELETE 1,9987 (documentation)."'"Then MERGE (or write) your BASIC"'"program. Then GO TO 9988."
9973 PRINT '"If your program itself uses"'"machine code that would occupy"'"the same area as TOOLKIT's"'"machine code, then do not load"'"your program's machine code"'"until you're done with TOOLKIT."
9974 LET ret=VAL "9976": GO TO VAL "9980"
9975
9976 PRINT TAB VAL "10";"PAGE 6"''"TOOLKIT's machine code was"'"written for SPECTRUM by John"'"Charlesworth. It appeared in"'"YOUR COMPUTER VOL 4, NO 4."''"TOOLKIT was adapted for 2068 by"'"Jack Dohany, (415)321-7684."''"TOOLKIT's machine code could"'"use some improvement, but at"'"least it works."'''TAB VAL "10";"THE END"
9977 LET ret=VAL "9947": GO TO VAL "9980"
9978
9979
9980 PRINT #VAL "1";AT VAL "0",VAL "0";"COPY MENU ENT=NEXT PAGE"
9981 IF INKEY$="" THEN GO TO VAL "9981"
9982 LET k$=INKEY$: IF k$=CHR$ VAL "13" THEN CLS : GO TO RET
9983 IF K$="M" OR k$="m" THEN RUN
9984 IF K$="C" OR k$="c" THEN COPY
9985 GO TO VAL "9981"
9986
9987
9988 CLS : PRINT TAB VAL "9";"** TOOLKIT **"'''"1: RENUMBER"''"2: KILL REMS"''"3: LIST VARIABLES"''"4: COMPACTION"''"5: MAKE BACKUP"''"6: STOP"''"OK TO RUN AFTER STOPPING": INPUT FFF: IF FFF<>VAL "1" THEN GO TO VAL "9992"
9989 LET TTT=VAL "100": LET SSS=VAL "10": IF FFF=VAL "1" THEN INPUT "NEW FIRST LINE: ";TTT,"STEP: ";SSS
9990 IF TTT>VAL "9999" OR TTT<VAL "1" OR SSS<VAL "1" OR SSS>TTT THEN GO TO VAL "9988"
9991 POKE VAL "23300",INT (TTT/VAL "256"): POKE VAL "23299",TTT-VAL "256"*PEEK VAL "23300": POKE VAL "23302",INT (SSS/VAL "256"): POKE VAL "23301",SSS-VAL "256"*PEEK VAL "23302": RANDOMIZE USR VAL "64048": PRINT AT VAL "20",VAL "0";"RENUMBER DONE": PAUSE VAL "200": GO TO VAL "9988"
9992 IF FFF=VAL "2" THEN RANDOMIZE USR VAL "64841": PRINT AT VAL "20",VAL "0";"REMS KILLED": PAUSE VAL "200": GO TO VAL "9988"
9993 IF FFF=VAL "3" THEN PRINT USR VAL "65184": STOP
9994 IF FFF=VAL "4" THEN RANDOMIZE USR VAL "65017": PRINT AT VAL "20",VAL "0";"COMPACTION DONE.": PAUSE VAL "200": GO TO VAL "9988"
9995 IF FFF=VAL "5" THEN CLS : PRINT AT VAL "10",VAL "0";"TWO-PART SAVE": SAVE "TK" LINE VAL "9998": BEEP VAL ".01",VAL "25": SAVE "TKB"CODE VAL "64048",VAL "1350": CLS : PRINT AT VAL "20",VAL "0";"REWIND AND PLAY TO VERIFY": VERIFY "": VERIFY ""CODE : GO TO VAL "9931"
9996 IF FFF=VAL "6" THEN STOP
9997 GO TO VAL "9988"
9998 CLEAR VAL "64048": BORDER VAL "0": PAPER VAL "0": INK VAL "7": CLS : PRINT AT VAL "10",VAL "0";"I'VE SET RAMTOP TO 64048"''"I'M LOADING THE 1350 BYTES"'"OF TOOLKIT CODE AT 64048": LOAD "TOOLKIT"CODE VAL "64048"
9999 GO TO VAL "9931"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


