Reader 2 walks the BASIC program area in memory and displays a byte-by-byte listing of the stored program, annotating each byte’s address, raw value, and decoded meaning. It reads the PROG pointer from system variable address 23635/23636 and the VARS pointer from 23627/23628 to determine the start and end of the program area. The program handles the five-byte floating-point number format (token 14) as a special case, printing descriptive labels sourced from a DATA statement. Line number and line length fields are decoded separately, with unprintable token bytes flagged explicitly.
Program Structure
The program is organized into a main loop (lines 10–75), a shared print subroutine at line 100, and a DATA block at line 200. Execution begins by capturing two system-variable pointers, then enters a sequential decode loop that never needs a line index — it simply advances the pointer variable p byte by byte through the BASIC area.
- Lines 10–15: Initialize
p(PROG, start of BASIC) andv(VARS, end of BASIC) from system variables. - Lines 20–35: Decode a two-byte line number and a two-byte line-length field, printing address, raw value, and a label via the shared subroutine.
- Line 40: Compute the end address of the current line (
le = p + le). - Lines 45–75: Main token loop — read one byte, branch on token value, advance
p, and loop back. - Line 100: Shared display subroutine — prints address, PEEK value, and positions the cursor for the caller’s annotation.
- Line 200: DATA strings labeling the five bytes of the embedded floating-point number format.
System Variable Usage
| Address | System Variable | Role in Program |
|---|---|---|
| 23635/23636 | PROG | Start address of the BASIC program area; initial value of p |
| 23627/23628 | VARS | Start of the variables area; signals end of BASIC when p reaches it |
Line Header Decoding
The TS2068 stores each BASIC line as: two-byte line number (high byte first), two-byte length (low byte first), then the tokenized statement bytes. The program reads the line number at line 20 as 256 * PEEK p + PEEK (p+1) (big-endian) and the length at line 30 as PEEK p + 256 * PEEK (p+1) (little-endian), correctly reflecting the actual on-disk format.
Token 14 — Embedded Floating-Point Numbers
Token value 14 (decimal) is the marker for an in-line five-byte binary floating-point constant that follows every numeric literal in tokenized BASIC. Lines 50 handles this case: it issues a RESTORE and then reads five labels from the DATA statement at line 200 ("FIVE", "BYTE", "EQUIV.", "OF", "NUMBER"), one per byte, printing them as annotations. This makes the otherwise opaque five bytes human-readable in the output.
Unprintable Token Handling
Line 55 checks whether the current byte is a control or keyword token in the range 0–15 or 24–255 — specifically, tokens 16–23 are color/attribute control codes that would corrupt the display if PRINTed directly. Any byte outside the range 16–23 is printed as CHR$ o; bytes within that range trigger the "(unprintable)" label at line 60.
Shared Subroutine and Output Layout
The subroutine at line 100 uses TAB stops to create a three-column layout: address at column 0, raw PEEK value at column 8, and the caller-supplied annotation starting at column 16. The trailing colon after TAB 16; and the RETURN leave the print position at column 16 so the calling line can immediately append its own text without an extra PRINT statement.
Loop Termination and Line Boundary Detection
Two checks guard the inner byte loop: at line 65, if p equals v (the VARS pointer), execution halts with STOP; at line 70, if p equals the precomputed line-end address le, control jumps back to line 20 to decode the next line header. This avoids any separate counter for bytes-remaining within a line.
Bugs and Anomalies
- Line length decoded before pointer advance: At line 30,
leis read from the currentp, which still points at the first byte of the length field. Line 40 then setsle = p + leusing the pre-advance value ofp. By the time the inner loop begins,phas been incremented twice more (once per length byte in line 35), solecorrectly points to the first byte past the end of the statement bytes — this is correct but relies on those two increments happening exactly.
Content
Source Code
10 LET p= PEEK 23635+256* PEEK 23636
15 LET v= PEEK 23627+256* PEEK 23628
20 LET n=256* PEEK p+ PEEK (p+1)
25 GO SUB 100:PRINT n; TAB 21;"( LINE ":LET p=p+1:GO SUB 100:PRINT TAB 21;"( NUMBER":LET P=P+1
30 LET le= PEEK p+256* PEEK (p+1)
35 GO SUB 100:PRINT le; TAB 21;"( LINE ":LET p=p+1:GO SUB 100:PRINT TAB 21;"( LENGTH":LET P=P+1
40 LET le=p+le
45 LET o= PEEK p
50 GO SUB 100:IF o=14 THEN RESTORE :PRINT TAB 21;"NUMBER:":FOR j=1 TO 5:LET p=p+1:GO SUB 100:READ n$:PRINT TAB 21;n$:NEXT j:GO TO 65
55 IF o<16 OR o>23 THEN PRINT TAB 16; CHR$ o:GO TO 65
60 PRINT TAB 16;"(unprintable)"
65 LET p=p+1:IF p=v THEN STOP
70 IF p=le THEN GO TO 20
75 GO TO 45
100 PRINT p; TAB 8; PEEK p; TAB 16;:RETURN
200 DATA "FIVE","BYTE","EQUIV.","OF","NUMBER"
9000 SAVE "READER 2" LINE 0
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
