This program reads the header block from a cassette tape and displays its contents on screen, decoding the file type, name, and metadata. It uses 27 bytes of Z80 machine code (POKEd into RAM at address 32768) that temporarily switches the TS2068 from its home ROM to the extension ROM, calls the ROM’s tape-loading routine at address 0x00FC to load a header block, then restores the home ROM. After loading, the BASIC code inspects the header buffer starting at address 32800: byte 0 holds the file type, bytes 32801–32810 hold the ten-character filename (printed with trailing spaces trimmed), and bytes 32811–32814 hold type-specific metadata such as autostart LINE number, array variable letter, or bytes start address and length. The program loops continuously, allowing multiple tape headers to be read and displayed in sequence.
Program Analysis
Program Structure
The program divides into four logical phases:
- Initialization (lines 10–60): Clears memory above 32767 and POKEs 27 bytes of Z80 machine code into addresses 32768–32794.
- User prompt (lines 100–130): Displays instructions and waits for a keypress before reading the tape.
- Tape read and decode (lines 140–270): Calls the machine code, then interrogates the loaded header buffer to print file type, name, and metadata.
- Loop and save (lines 280, 9999): Returns to line 150 for another header read; line 9999 saves the program to tape.
Machine Code Routine
The 27-byte routine at 0x8000 (32768) performs a ROM bank switch to access the TS2068 extension ROM’s tape-loading routine, then restores the home ROM:
| Address | Hex | Mnemonic | Purpose |
|---|---|---|---|
| 8000 | F3 | DI | Disable interrupts |
| 8001 | 3E 80 | LD A,80 | Select extension ROM bank |
| 8003 | D3 FF | OUT (FF),A | Write to ROM select port |
| 8005 | 3E 01 | LD A,01 | Enable extension ROM |
| 8007 | D3 F4 | OUT (F4),A | Write to secondary ROM port |
| 8009 | 3E 00 | LD A,00 | Set header load flag (A=0) |
| 800B | DD 21 20 80 | LD IX,8020 | Point IX to load buffer (32800) |
| 800F | 37 | SCF | Set carry flag (LOAD, not VERIFY) |
| 8010 | CD FC 00 | CALL 00FC | Call ROM tape-load routine |
| 8013 | 3E 00 | LD A,00 | Select home ROM |
| 8015 | D3 FF | OUT (FF),A | Restore ROM select port |
| 8017 | D3 F4 | OUT (F4),A | Restore secondary ROM port |
| 8019 | FB | EI | Re-enable interrupts |
| 801A | C9 | RET | Return to BASIC |
The header block (17 bytes) is loaded at address 32800 (0x8020). Byte 0 (address 32800) is the file type; bytes 1–10 (32801–32810) are the filename; bytes 11–12 (32811–32812) are the data length; bytes 13–14 (32813–32814) hold the autostart line or start address depending on file type.
Header Buffer Decoding
Lines 160–265 decode all four standard tape file types by examining PEEK 32800:
- Type 0 – Program: Prints
"Program: "and, if the autostart line (PEEK 32813+256*PEEK 32814) is less than 9999, printsLINE n. - Type 1 – Number array: Prints the array variable letter via
CHR$ (PEEK 32814-64)and the element count as(length-3)/5. - Type 2 – Character array: Prints the array variable using
CHR$ (PEEK 32814-128)and the element count asPEEK 32811+256*PEEK 32812-3. - Type 3 – Code/Bytes: Prints start address and length from bytes 13–14 and 11–12 respectively.
Filename Trimming Technique
Lines 210–240 implement a right-trim of the ten-character filename field. The loop at line 210 scans backwards from address 32810 to 32801, recording in mark the highest address containing a non-space character. The forward loop at line 240 then prints only characters up to that address, avoiding trailing space padding that the tape format mandates.
Key BASIC Idioms
PEEK j+256*PEEK (j+1)is the standard idiom for reading a 16-bit little-endian word from two consecutive memory addresses.POKE 23692,2afterRANDOMIZE USRresets the error scroll counter, preventing the scroll? prompt from interrupting the display loop.- Line 130 uses
IF INKEY$="" THEN GO TO 130as a busy-wait keypress loop. - The quotation marks around the filename are printed as literal
"""strings — a single quote inside a PRINT string is output by doubling the delimiter character.
Anomalies and Notes
- The machine code at 800B encodes
LD IX,8020asDD 21 20 80. Since the header is 17 bytes, data occupies 32800–32816, safely within the cleared region. - The autostart-line check at line 250 uses
<9999rather than the conventional<=9999or<65535. A valid autostart line of exactly 9999 would be silently suppressed, though this is an edge case unlikely to arise in practice. - Line 9999 saves the program itself to tape;
BEEP 1,32provides an audible end-of-program signal. - The
CLEAR 32767at line 10 sets RAMTOP just below the machine code area, protecting the routine from being overwritten by the BASIC system stack.
Content
Image Gallery
Source Code
10 CLEAR 32767
20 FOR j=32768 TO 32794
30 READ k
40 POKE j,k
50 NEXT j
60 DATA 243,62,128,211,255,62,1,211,244,62,0,221,33,32,128,55,205,252,0,62,0,211,255,211,244,251,201
70 REM The DATA Statement Contains The Machine code ; 8000 DI ;Disable Int. 8001 LD A,80 ;\ 8003 OUT (FF),A ; \Switch To 8005 LD A,01 ; /Extension 8007 OUT (F4),A ;/ ROM 8009 LD A,00 ;LOAD Header 800B LD IX,8020 ;LOAD It Here 800F SCF ;LOAD Flag 8010 CALL 00FC ;LOAD Routine 8013 LD A,00 ;\ 8015 OUT (FF),A ; *Restore 8017 OUT (F4),A ;/ Home ROM 8019 EI ;Enable Int. 801A RET ;All Done
100 CLS
110 PRINT AT 10,5;"Program Header Display"
120 PRINT AT 12,0;"Start The Tape And Press Any Key"
130 IF INKEY$="" THEN GO TO 130
140 CLS
150 RANDOMIZE USR 32768: POKE 23692,2
160 IF PEEK 32800=0 THEN PRINT "Program: ";
170 IF PEEK 32800=1 THEN PRINT "Number array: ";
180 IF PEEK 32800=2 THEN PRINT "Character array: ";
190 IF PEEK 32800=3 THEN PRINT "Bytes: ";
200 LET mark=0: PRINT """";
210 FOR j=32810 TO 32801 STEP -1
220 IF PEEK j<>32 THEN IF mark=0 THEN LET mark=j
230 NEXT j
240 FOR j=32801 TO mark: PRINT CHR$ PEEK j;: NEXT j
245 PRINT """";
250 IF PEEK 32800=0 THEN IF PEEK 32813+256*PEEK 32814<9999 THEN PRINT " LINE ";PEEK 32813+256*PEEK 32814;
255 IF PEEK 32800=1 THEN PRINT " ";CHR$ (PEEK 32814-64);"(";(PEEK 32811+256*PEEK 32812-3)/5;")";
260 IF PEEK 32800=3 THEN PRINT " ";PEEK 32813+256*PEEK 32814;",";PEEK 32811+256*PEEK 32812;
265 IF PEEK 32800=2 THEN PRINT " ";CHR$ (PEEK 32814-128);"$(";PEEK 32811+256*PEEK 32812-3;")";
270 PAUSE 150: PRINT ""
280 GO TO 150
9999 SAVE "HEADER": BEEP 1,32
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.