Programming Tools

This file is part of and ISTUG Public Domain Library 6. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 2068

This program is a multi-utility loader that installs several machine code tools into high RAM: an AUTOLINE facility (automatic line numbering), a TRACER (program execution tracer with adjustable delay), a COMMAND key handler (using “!” as a function key), and a USER KEYS extension. Each utility is encoded as a string of space-padded three-digit decimal byte values in the variable `a$`, then POKEd byte-by-byte into memory starting around address 65024. All four utilities make use of Interrupt Mode 2 (IM2), redirecting the interrupt vector to install custom interrupt service routines in high memory. The POKE/LOAD addresses and RANDOMIZE USR entry points are printed to the screen before installation so the user can note them down.


Program Analysis

Program Structure

The listing is divided into four independent sections, each self-contained and selectable by running the appropriate lines. They share a common byte-encoding/POKEing idiom but install different machine code payloads at overlapping high-memory addresses.

SectionLinesPurposeMC Load AddressEntry Points
AUTOLINE10–499Automatic line numbering65024–65267USR 65120 (on), USR 65124 (off)
TRACER500–999Program execution tracer65100–65337USR 65100 (on), USR 65104 (off)
COMMAND1000–1499“!” function key handler65024–65186USR 65110 (on), USR 65100 (off)
USER KEYS1500–1999User-definable key extensions65024–65182USR 65126 (on), USR 65122 (off)

Byte Encoding Idiom

Each utility stores its machine code as a sequence of space-padded three-digit decimal numbers concatenated into the string variable a$ across multiple LET statements. The installation loop then extracts bytes one at a time:

  POKE f, VAL a$( TO 3): LET a$=a$(4 TO )

Each byte occupies exactly three characters (e.g., "197", " 6", " 0"), making slicing with a fixed stride of 4 characters reliable. Using VAL on a substring avoids needing a separate numeric array and is a well-known BASIC memory optimization.

Interrupt Mode 2 (IM2) Usage

All four utilities explicitly state they use IM2 (Interrupt Mode 2). The machine code preambles visible in the byte streams contain the Z80 opcodes 237 94 (IM 2) and 237 86 (IM 1), which switch between interrupt modes. The routines install a custom interrupt vector table and ISR (Interrupt Service Routine) in high RAM, allowing keyboard scanning or line-number injection to happen transparently between BASIC statements without user intervention.

Memory Layout and Address Gaps

The AUTOLINE and COMMAND loaders both skip a region of addresses during POKEing. In AUTOLINE, line 210 checks IF f=65060 THEN LET f=65120, jumping over addresses 65060–65119. COMMAND does the same, jumping from 65060 to 65100 (line 1160). This preserves a gap presumably used by a shared IM2 vector table or system workspace that must not be overwritten during loading.

AUTOLINE Detail

AUTOLINE intercepts keyboard input via IM2 to inject automatically incremented line numbers as the user types. The user is told to POKE 65192 with the desired step value before activating via RANDOMIZE USR 65120. Address 65192 thus acts as a configuration byte within the machine code block.

TRACER Detail

The TRACER utility adds a configurable delay between BASIC line executions, useful for watching a program run in slow motion. POKE 65246,n sets the delay, where n ranges from 1–255 (with 0 giving the longest delay, wrapping the counter). Line 560 uses DELETE 1,9999 — a TS2068-specific keyword — to clean up the loader BASIC program after installation, leaving only the machine code resident.

COMMAND Detail

The COMMAND utility repurposes the ! character as a function key. The user places the action to be triggered in line 1 as a REM statement. Line 1070 contains REM :1,200, which appears to encode parameters (target line 1, some offset 200) for the machine code to parse from the REM text. The on/off entry points are RANDOMIZE USR 65110 and RANDOMIZE USR 65100.

USER KEYS Detail

The USER KEYS section loads machine code and also reads additional configuration DATA from lines 1690–1700. Lines 1640–1670 implement a custom DATA reader that iterates from address 60032 upward, POKEing non-zero bytes and using zero as a record delimiter. The boundary check (a-59999)/32=INT((a-59999)/32) aligns writes to 32-byte boundaries. Lines 1690–1700 provide two small key-mapping records, each terminated by 251,0.

Notable Anomaly: Commented-Out POKE in USER KEYS

Line 1820 reads REM POKE f,VAL a$( TO 3): LET a$=a$(4 TO ) — the actual POKEing statement is commented out with REM. This means the USER KEYS FOR loop (lines 1800–1830) iterates without installing any bytes, rendering that section non-functional as listed. This is likely an incomplete or work-in-progress section (consistent with the ?Complete? remark in line 1500).

Key BASIC Idioms

  • PAUSE 0 halts execution until a key is pressed — used as a “press any key” gate before installation.
  • VAL a$( TO 3) extracts and evaluates a fixed-width numeric substring without requiring an array.
  • LET a$=a$(4 TO ) advances the string pointer, consuming the byte just processed.
  • Multi-segment string concatenation across successive LET a$=a$+ lines works around the line-length limit.
  • GO TO VAL "number" is used in REM comments to document the intended startup line for each saved CODE block.
  • Line 499 and similar lines pack STOP and SAVE instructions together with : separators, keeping save instructions in the listing without being accidentally executed.

Content

Appears On

Library tape of the Indiana Sinclair Timex User’s Group.

Related Products

Related Articles

Related Content

Image Gallery

Programming Tools

Source Code

   10 REM AUTOLINE
   20 PRINT "POKE 65192 WITH STEP REQUIRED"
   30 PRINT " RANDOMIZE USR 65120 TO TURN ON"
   40 PRINT " RANDOMIZE USR 65124 TO TURN OFF"
   50 PRINT ''"NOTE THESE NUMBERS AND          PRESS ANY KEY WHEN READY"
   60 PAUSE 0
   70 RANDOMIZE USR 65024
  100 STOP 
  110 REM CLEAR 65023: LOAD "AL"CODE : GO TO 10
  120 LET a$="197213229245 33  0251  6  0 54252 35 16251 54252 62195 50252252 33105254 34253252 62251237 71241"
  130 LET a$=a$+"225209193201237 94201  0237 86201  0  0255243245229213197 58104254254  0 32 39 58130 92254 32 32113 58131 92"
  140 LET a$=a$+"254 23 32106 33  8 92126254 12 40 98 33  4 92126254 13 40  4254255 32 86 62  4 50104254 58104254 61 50104254 42 73 92 17 10  0 25  1 24252205209"
  150 LET a$=a$+"254254  3 40 57  1156255205209254254  2 40 47  1246255205209254254  1 40 37  1255255205209254 24 29175  9 60 56252237 66"
  160 LET a$=a$+" 61198 48229 33  8 92119 58 59 92203239 33 59 92119225 58104254201193209225241251201"
  200 FOR f=65024 TO 65267
  210 IF f=65060 THEN LET f=65120
  220 POKE f,VAL a$( TO 3): LET a$=a$(4 TO )
  230 NEXT f
  499 STOP : REM SAVE "AUTOLINE" LINE 110: SAVE "AL"CODE 65024,250: STOP 
  500 REM            TRACERNote--This program uses IM2.
  510 RANDOMIZE USR 65302
  520 PRINT "Use RANDOMIZE USR 65100"'"     to turn TRACER ON"
  530 PRINT '"Use RANDOMIZE USR 65104"'"     to turn TRACER OFF"
  540 PRINT '"Use POKE 65246,n to change"'"delay speed, where n is a"'"number from 1 to 255"'" (the bigger the number"'" the longer the delay"'" except that 0 is the"'" longest)"
  550 PRINT '"Take note of these addresses"
  560 PRINT ''"Press any key when ready": PAUSE 0: DELETE 1,9999
  570 STOP 
  580 REM CLEAR 64511: LOAD "T"CODE : GO TO 50
  590 STOP 
  600 LET a$="237 94201  0237 86201  0243245197213229  0 58 70 92 60202233254 42 69 92 17232  3205 10255229205"
  610 LET a$=a$+"241254 17 24 64205  1255225 17100  0205 10255229205241254 17 25 64205  1255225 17 10  0205 10255229205241254 17 26 64205  1255225125205241254 17"
  620 LET a$=a$+" 27 64205  1255 62 10205241254 17 28 64205  1255 42 71 92 38  0 17100  0205 10255229205241254 17 29 64205  1255225 17 10  0205 10255229205241254"
  630 LET a$=a$+" 17 30 64205  1255225125205241254 17 31 64205  1255  6 60197  6  0  0  0 16252193 16246225209193241251195 56  0198 48111 38  0 41 41 41237 91 54"
  640 LET a$=a$+" 92175237 90201  6  8126 18 35 20 16250201175183237 82 60 48250183237 90 61201197213229245 33  0252  6  0 54253 35 16251 54253 62195 50253253 33"
  650 LET a$=a$+" 84254 34254253 62252237 71241225209193201"
  660 FOR f=65100 TO 65337
  670 POKE f,VAL a$( TO 3): LET a$=a$(4 TO )
  680 NEXT f
  999 STOP : REM SAVE "TRACER" LINE 130: SAVE "T"CODE 65100,240: VERIFY "": VERIFY ""CODE 
 1000 REM     COMMAND
 1010 PRINT " COMMAND--USE ! AS FUNCTION KEY "
 1020 PRINT ''"ENTER AS LINE 1 A REM STATEMENT WITH A DEFINED COMMAND TO BE    ACTUATED BY THE USE OF THE ! KEY"
 1030 PRINT '"USE RANDOMIZE USR 65110 TO TURN THE COMMAND ON"
 1040 PRINT '"USE RANDOMIZE USR 65100 TO TURN THE COMMAND OFF"
 1050 PRINT ''"TAKE NOTE OF THESE USR NUMBERS  THEN PRESS ANY KEY TO CONTINUE "
 1060 PAUSE 0: RANDOMIZE USR 65024
 1070 REM :1,200
 1080 STOP 
 1090 REM CLEAR 64255: LOAD "C"CODE : GO TO 10
 1100 LET a$="197213229245 33  0251  6  0 54252 35 16251 54252 62195 50252252 33105254 34253252 62251237 71241225209193201"
 1120 LET a$=a$+"237 86201  0  0  0  0  0  0  0237 94 33 91104 34103254201  0  0  0  0  0  0  0  0 91104255243245229 42103254125254 91 32  8 33  8 92"
 1130 LET a$=a$+"126254 33 32 34 42103254126 35 34103254 33  8 92119 58 59 92203239 33 59 92119 58  8 92254 13 32  6 33 91104 34103254225241251201"
 1150 FOR f=65024 TO 65186
 1160 IF f=65060 THEN LET f=65100
 1170 POKE f,VAL a$( TO 3): LET a$=a$(4 TO )
 1180 NEXT f
 1499 STOP : REM SAVE "COMMAND" LINE 170: SAVE "C"CODE 65024,165
 1500 REM USER KEYS  ?Complete? 
 1510 CLS 
 1520 PRINT "*** USER KEYS (WITH IM2)***"
 1530 PRINT '"USE RANDOMIZE USR 65126 TO "'"TURN PROGRAM ON"
 1540 PRINT '"USE RANDOMIZE USR 65122 TO "'"TURN PROGRAM OFF"
 1550 PRINT '"USE RANDOMIZE USR 65024 TO "'"RESTART AFTER 'NEW'"
 1560 PRINT ''"NOTE ABOVE NUMBERS AND PRESS"'"ANY KEY TO CONTINUE "
 1570 PAUSE 0
 1580 RANDOMIZE USR 65024
 1590 RANDOMIZE USR 65126
 1600 REM :1,500: STOP 
 1610 STOP 
 1620 REM CLEAR 59999: LOAD "USER KEYS"CODE : GO TO 210
 1630 REM DATA LINES
 1640 RESTORE 1690
 1650 FOR a=60032 TO 1e5: READ z: IF z<>0 THEN POKE a,z: NEXT a
 1660 IF (a-59999)/32=INT ((a-59999)/32) THEN NEXT a
 1670 LET a=a+1: POKE a-1,0: GO TO 1660
 1680 REM DATA LINES START AT 300
 1690 DATA 231,53,58,218,53,58,217,57,58,251,0
 1700 DATA 231,55,58,218,55,58,217,57,58,251,0
 1710 GO TO 1510
 1720 LET a$="197213229245 33  0251  6  0 54252 35 16251 54252 62195 50252252 33105254 34253252 62251237 71241225209193201"
 1730 LET a$=a$+"237 86201  0237 94201255243229213197245205176  2 62 32186194153254 38  0107 41 41 41 41 41 17 96234 25126254  0 40  8 35229205231 10225 24"
 1740 LET a$=a$+"243205176  2 62 32187 32248241193209225251201"
 1800 FOR f=65024 TO 65182
 1810 IF f=65060 THEN LET f=65122
 1820 REM POKE f,VAL a$( TO 3): LET a$=a$(4 TO )
 1830 NEXT f
 1999 STOP : REM SAVE "USER KEYS" LINE 150: SAVE "USER KEYS"CODE 65024,165: PRINT "REWIND FOR VERIFY": VERIFY "": VERIFY ""CODE 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top