Streams and Channels

Date: 198x
Type: Program
Platform(s): TS 2068

This program is a diagnostic utility that displays the contents of the system variable STRMS (streams table) at addresses 23568–23605, showing each two-byte word as a 16-bit little-endian value alongside its channel label (−3 through 15). It then reads the CHANS system variable (from addresses 23631–23632) to locate and display the 21-byte channel definition table in RAM, printing each entry’s output routine address, input routine address, and device specifier character. The program uses OVER 1 printing and PLOT/DRAW to create an overlay grid illustrating the table layout. A reference page lists the standard device specifier codes (75=K keyboard, 83=S screen, 82=R RAM write, 80=P printer), and the utility includes options to copy output to the printer by poking channel 0’s device byte with 80 (printer) or restoring it with 83 (screen). The program explicitly notes it runs on both the standard TS2068 ROM and the TS2068 with a Spectrum ROM, with different CHANS table locations between the two configurations.


Program Analysis

Program Structure

The program is organized into five logical sections separated by keypress pauses that optionally trigger a printer copy:

  1. Lines 110–315: Loop over the STRMS system variable area (23568–23605), printing each 16-bit word and its channel label (−3 through 15).
  2. Lines 315–361: Pause/copy prompt, then display a device specifier reference page (K, S, R, P codes).
  3. Lines 401–521: Read CHANS pointer, walk the 21-byte channel table, display output/input routine addresses and device bytes, then draw a graphic overlay with OVER 1 and PLOT/DRAW.
  4. Lines 530–562: Compatibility note and printer-poke instructions, final menu offering Save, Copy, Run, or Stop.
  5. Lines 9997–9998: STOP and SAVE stub.

STRMS Table Display (Lines 110–310)

The FOR loop steps by 2 from 23568 to 23605, covering 19 two-byte STRMS entries (channels −3 through 15). Each 16-bit pointer is read with the standard little-endian idiom:

PEEK N + PEEK (N+1) * 256

Rather than using a computed channel label, each address is matched with a dedicated IF at lines 120–300 — one line per channel. This is verbose but ensures exact label strings including the aligned spacing for negative channel numbers and double-digit channel numbers.

CHANS Table Display (Lines 401–510)

The CHANS system variable pointer is read at line 401:

LET C = PEEK 23631 + PEEK 23632 * 256

Lines 410–450 then manually walk four complete 5-byte channel entries plus the terminating byte. Each entry consists of:

  • 2 bytes — output routine address (printed as a 16-bit word)
  • 2 bytes — input routine address (printed as a 16-bit word)
  • 1 byte — device specifier character (printed as both numeric and CHR$)

The variable C is advanced manually between entries with LET C = C + 3 (stepping past the two bytes already consumed by the inner FOR loop plus the device byte). This pointer arithmetic is done entirely in BASIC without any machine code assistance.

OVER 1 Overlay Technique (Lines 460–510)

After printing the CHANS table data, lines 460–510 use OVER 1 to XOR-draw column separator lines and header labels over the already-printed content. The sequence is:

  • Line 460: OVER 1 enabled
  • Line 470–500: Column headers (“OUTPUT ROUTINE ADR”, “INPUT ROUTINE ADDR”, “DEVICE SPEC”) printed four times at successive rows using PRINT AT and TAB
  • Line 511: A box drawn with PLOT/DRAW at pixel coordinates to bracket the table area
  • Line 510: OVER 0 to restore normal mode

This produces a visual grid aligned with the printed data without erasing it — a technique that depends on the precise character positions used in the earlier PRINT statements.

Pause/Copy/Print Idiom (Lines 315, 360, 520, 560)

Each section ends with a consistent pattern printed to stream 1 (the lower information line):

PRINT #1;AT 0,0;"ANY KEY TO CONTINUE, Z TO COPY": PAUSE 0: IF INKEY$="Z" THEN COPY : CLS

The PAUSE 0 followed by INKEY$ is the standard efficient keypress-wait idiom. The COPY command sends the current screen to the printer. Note that after COPY the program falls through to the next line (CLS) rather than branching away, so the screen is cleared either way.

Printer Redirect Information (Lines 530–540)

The program documents a useful technique: poking the device specifier byte of channel 0 with 80 (ASCII “P”) redirects all PRINT output to the printer. The correct address differs between ROM configurations:

ConfigurationPOKE AddressValue for PrinterValue to Restore
TS2068 native ROM266978083
TS2068 with Spectrum ROM237438083

This works because the CHANS table is located at different addresses under the two ROMs, but the device specifier byte within the screen channel entry is in both cases reachable by these absolute addresses.

Notable Anomalies and Observations

  • Line 315 has a formatting issue: COPY : CLS is on the same line as the condition, meaning CLS executes unconditionally if “Z” is pressed (after COPY), but if any other key is pressed the line simply falls through to line 316 which is also CLS — so CLS always runs. This is intentional cleanup, not a bug.
  • Line 450 has a stray single-quote inside a string literal: PRINT '"1 ";C;... — the ' before "1 " is a newline token outside the string, so this prints a blank line then the terminator byte entry. Correct behavior.
  • The final menu at line 560 checks INKEY$ at lines 561–562 after the PAUSE 0 has already consumed one keypress at line 560. Unless the key is held down, lines 561–562 will typically read an empty string, making the “R” and “S” options unreliable. This is a minor design flaw.
  • Line 562 does CLEAR : GO TO 9998 to reach the SAVE line, which erases all variables before saving — a common pattern to produce a clean tape file.

Content

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.
One of a series of library tapes. Programs on these tapes were renamed to a number series. This tape contained

Related Products

Related Articles

Related Content

Image Gallery

Streams and Channels

Source Code

  110 FOR N=23568 TO 23605 STEP 2
  120 IF N=23568 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL -3)"
  130 IF N=23570 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL -2)"
  140 IF N=23572 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL -1)"
  150 IF N=23574 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  0)"
  160 IF N=23576 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  1)"
  170 IF N=23578 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  2)"
  180 IF N=23580 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  3)"
  190 IF N=23582 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  4)"
  200 IF N=23584 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  5)"
  210 IF N=23586 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  6)"
  220 IF N=23588 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  7)"
  230 IF N=23590 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  8)"
  240 IF N=23592 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL  9)"
  250 IF N=23594 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL 10)"
  260 IF N=23596 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL 11)"
  270 IF N=23598 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL 12)"
  280 IF N=23600 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL 13)"
  290 IF N=23602 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL 14)"
  300 IF N=23604 THEN PRINT N;TAB 6;PEEK N+PEEK (N+1)*256;TAB 10;"(CHANNEL 15)"
  310 NEXT N
  315 PRINT #1;AT 0,0;"ANY KEY TO CONTINUE, Z TO COPY": PAUSE 0: IF INKEY$="Z" THEN COPY : CLS 
  316 CLS 
  350 PRINT "DEVICE SPEC"''"75=K=KEYBOARD"''"83=S=SCREEN"''"82=R=RAMWRITE"''"80=P=PRINTER"
  360 PRINT #1;AT 0,0;"ANY KEY TO CONTINUE, Z TO COPY": PAUSE 0: IF INKEY$="Z" THEN COPY : CLS 
  361 CLS 
  401 LET C=PEEK 23631+PEEK 23632*256
  405 PRINT "CHANS=PEEK 23631+PEEK 23632*256"''"CHANS=";C;TAB 12;"21 BYTE TABLE"
  410 PRINT : FOR N=C TO C+3 STEP 2: PRINT "2 ";N;TAB 8;PEEK N+PEEK (N+1)*256: NEXT N: LET C=C+2: PRINT "1 ";N;TAB 8;PEEK N;TAB 11;CHR$ PEEK N
  420 LET C=C+3: PRINT : FOR N=C TO C+3 STEP 2: PRINT "2 ";N;TAB 8;PEEK N+PEEK (N+1)*256: NEXT N: LET C=C+2: PRINT "1 ";N;TAB 8;PEEK N;TAB 11;CHR$ PEEK N
  430 LET C=C+3: PRINT : FOR N=C TO C+3 STEP 2: PRINT "2 ";N;TAB 8;PEEK N+PEEK (N+1)*256: NEXT N: LET C=C+2: PRINT "1 ";N;TAB 8;PEEK N;TAB 11;CHR$ PEEK N
  440 LET C=C+3: PRINT : FOR N=C TO C+3 STEP 2: PRINT "2 ";N;TAB 8;PEEK N+PEEK (N+1)*256: NEXT N: LET C=C+2: PRINT "1 ";N;TAB 8;PEEK N;TAB 11;CHR$ PEEK N
  450 LET C=C+3: PRINT '"1 ";C;TAB 8;PEEK C
  460 OVER 1: PRINT AT 2,0;"_________________________"
  470 PRINT AT 4,14;"OUTPUT ROUTINE ADR";TAB 14;"INPUT ROUTINE ADDR";TAB 14;"DEVICE SPEC"
  480 PRINT 'TAB 14;"OUTPUT ROUTINE ADR";TAB 14;"INPUT ROUTINE ADDR";TAB 14;"DEVICE SPEC"
  490 PRINT 'TAB 14;"OUTPUT ROUTINE ADR";TAB 14;"INPUT ROUTINE ADDR";TAB 14;"DEVICE SPEC"
  500 PRINT 'TAB 14;"OUTPUT ROUTINE ADR";TAB 14;"INPUT ROUTINE ADDR";TAB 14;"DEVICE SPEC"
  510 OVER 0
  511 PLOT 0,87: DRAW 255,0: DRAW 0,8: DRAW -255,0: DRAW 0,-7
  520 PRINT #1;AT 0,0;"ANY KEY TO CONTINUE, Z TO COPY": PAUSE 0: IF INKEY$="Z" THEN COPY : CLS 
  521 CLS 
  530 PRINT "THIS PROGRAM WORKS ON BOTH THE  TS2068 AND THE TS2068 WITH THE  SPECTRUM ROM."''"THE VARIABLE ADDRESSES ARE THE  SAME BUT THE 21 BYTE TABLE IS INDIFFERENT LOCATIONS."
  540 PRINT '"BY POKING 26697,80 ON THE 2068  OR POKING 23743,80 ON THE 2068  WITH A SPECTRUM ROM ALL ""PRINT"" STATEMENTS WILL BE LLPRINTED."''"TO RETURN TO NORMAL POKE THE    SAME ADDRESS WITH 83."
  560 PRINT #1;AT 0,0;"S TO SAVE              Z TO COPY"'"ANY KEY TO STOP        R TO RUN": PAUSE 0: IF INKEY$="Z" THEN COPY : CLS 
  561 IF INKEY$="R" THEN RUN 
  562 IF INKEY$="S" THEN CLEAR : GO TO 9998
 9997 STOP 
 9998 SAVE "STRMSCHANS"

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

People

No people associated with this content.

Scroll to Top