Header

Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Tape, Utility

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:

  1. Initialization (lines 10–60): Clears memory above 32767 and POKEs 27 bytes of Z80 machine code into addresses 32768–32794.
  2. User prompt (lines 100–130): Displays instructions and waits for a keypress before reading the tape.
  3. Tape read and decode (lines 140–270): Calls the machine code, then interrogates the loaded header buffer to print file type, name, and metadata.
  4. 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:

AddressHexMnemonicPurpose
8000F3DIDisable interrupts
80013E 80LD A,80Select extension ROM bank
8003D3 FFOUT (FF),AWrite to ROM select port
80053E 01LD A,01Enable extension ROM
8007D3 F4OUT (F4),AWrite to secondary ROM port
80093E 00LD A,00Set header load flag (A=0)
800BDD 21 20 80LD IX,8020Point IX to load buffer (32800)
800F37SCFSet carry flag (LOAD, not VERIFY)
8010CD FC 00CALL 00FCCall ROM tape-load routine
80133E 00LD A,00Select home ROM
8015D3 FFOUT (FF),ARestore ROM select port
8017D3 F4OUT (F4),ARestore secondary ROM port
8019FBEIRe-enable interrupts
801AC9RETReturn 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, prints LINE 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 as PEEK 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,2 after RANDOMIZE USR resets the error scroll counter, preventing the scroll? prompt from interrupting the display loop.
  • Line 130 uses IF INKEY$="" THEN GO TO 130 as 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,8020 as DD 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 <9999 rather than the conventional <=9999 or <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,32 provides an audible end-of-program signal.
  • The CLEAR 32767 at line 10 sets RAMTOP just below the machine code area, protecting the routine from being overwritten by the BASIC system stack.

Content

Appears On

Library tape from the Sinclair Computer Users Society (SINCUS).

Related Products

Related Articles

Related 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.

People

No people associated with this content.

Scroll to Top