This program reads a tape header block using a machine code routine loaded at address 32768 and displays the metadata — file type, name, length, and start address — decoded from the header bytes stored at addresses 33280–33294. It reconstructs a ready-to-type SAVE command string, including the correct keyword (LINE, CODE, DATA, or DATA$) based on the file type byte at 33280. A lookup table at line 230 maps the eight possible header type codes (0–3 covering BASIC, numeric array, string array, and code) to their display names and BASIC SAVE keywords. The program also handles the special case of a SCREEN$ file by detecting address 16384 and length 6912. Users can optionally send the SAVE command to a printer via LPRINT, reload another header, or re-save the utility itself.
Program Analysis
Program Structure
The program divides into four logical phases:
- Initialization (lines 10–30): Loads the companion machine code block “Saver code” to address 32768, then zeros two bytes at 33293–33294.
- Header capture (lines 40–70): Prompts the user to play a tape, calls the machine code at
USR 32768to read a tape header, then beeps to indicate completion. - Data decoding (lines 80–170): Parses the raw header bytes from 33280–33294, looks up the file type, trims the filename, and reconstructs the SAVE command string.
- Output and menu (lines 180–240): Displays options to print via LPRINT, load another header, or re-save the utility; line 240 performs the re-save.
Header Memory Map
The machine code routine deposits the decoded header fields into a fixed block of RAM starting at 33280. The layout used by the BASIC decoding code is:
| Address | Content | Length |
|---|---|---|
| 33280 | File type byte (0–3) | 1 |
| 33281–33290 | Filename (10 chars, space-padded) | 10 |
| 33291–33292 | Parameter 1 (length / LINE number) | 2 |
| 33293–33294 | Parameter 2 (start address / array letter) | 2 |
This layout mirrors the standard Spectrum tape header block structure, offset by 33280 from address 0. Parameter 1 (L) is computed as (PEEK 33292)*256+PEEK 33291 (little-endian) and Parameter 2 (S) similarly from 33293–33294.
File Type Lookup Table
Line 230 holds a DATA statement with four pairs of strings: a display name and a SAVE keyword fragment for each of the four header types (0 = BASIC, 1 = numeric array, 2 = string array, 3 = machine code). Line 80 reads through Q iterations (0 to T, where T is the type byte) to land on the correct pair, storing them in T$ and D$.
Filename Trimming
Lines 100–110 scan the 10-character filename string n$ from right to left, stopping at the last non-space character. The resulting index c is then used as a TO-slice bound — N$( TO c) — throughout the output lines, neatly stripping trailing spaces without any string manipulation function.
SAVE Command Reconstruction
Lines 120–150 build the extra parameter string E$ depending on file type. For BASIC (type 0), s$ is set to " (Line #)" and E$ to the autostart line number. For code (type 3), E$ becomes start,length. The special case at line 150 detects a SCREEN$ save (start 16384, length 6912) and substitutes the keyword SCREEN$, clearing D$ so the output reads SAVE "name" SCREEN$ correctly.
Machine Code Component
The 472-byte machine code block is loaded at address 32768 (just below the BASIC program area set by CLEAR 32000) and called via RANDOMIZE USR 32768 at line 60. The routine is responsible for the low-level tape reading that the Spectrum ROM’s own LOAD mechanism would ordinarily handle; using machine code allows the header bytes to be deposited into a known RAM location without affecting the BASIC program. The CLEAR 32000 at line 10 ensures the machine code area is protected from BASIC memory management.
User Interface Loop
Lines 180–220 implement a simple three-option menu using PAUSE 0 followed by INKEY$ checks. This is a standard keypress-detection idiom: PAUSE 0 waits until any key is pressed, then the subsequent IF INKEY$= tests read the still-held key. If none of the three keys match, line 220 loops back to line 190 to re-test.
Notable Anomalies
- Line 30 pre-zeros 33293–33294, which correspond to the start-address parameter for code files. This prevents a stale value being displayed if the machine code routine does not overwrite them (e.g., for BASIC file headers where this field is unused).
- The variable
s(lowercase) at line 150 refers to the same value asScomputed at line 130; Spectrum BASIC is case-insensitive for variable names of length > 1, but single-letter variables are case-sensitive — howeverSandsare the same single-letter variable in Spectrum BASIC (keywords are tokenized; variable names are stored in lowercase internally). This works correctly. - The
DATAat line 230 contains only four type entries (types 0–3), which matches the complete set of valid Spectrum header types, so no out-of-range read can occur under normal tape operation.
Content
Source Code
10 CLEAR 32000: LOAD "Saver code"CODE : BEEP .2,22
20 CLS : PRINT TAB 10;" S A V E R ";AT 4,9;"THIS PROGRAM";AT 6,6;"DISPLAYS OR PRINTS";AT 8,4;"TAPE HEADER INFORMATION"
30 POKE 33293,0: POKE 33294,0
40 PRINT FLASH 1;AT 18,3;" PRESS ENTER AND START TAPE "; FLASH 0;AT 20,11;"WHEN READY"
50 PAUSE 0: PRINT AT 18,1;" ";" NOW LOADING HEADER ";AT 20,8;"STOP TAPE AT BEEP"
60 RANDOMIZE USR 32768
70 BEEP .8,22: CLS
80 LET T=PEEK 33280: RESTORE 230: FOR Q=0 TO T: READ T$: READ D$: NEXT Q
90 LET n$="": FOR q=33281 TO 33290: LET n$=n$+CHR$ (PEEK q): NEXT q
100 FOR q=10 TO 1 STEP -1: IF n$(q)=" " THEN NEXT q
110 LET c=q
120 LET s$=" (Address)": IF T=0 THEN LET s$=" (Line #)"
130 LET L=(PEEK 33292)*256+PEEK 33291: LET S=(PEEK 33294)*256+PEEK 33293
140 LET E$="": IF T=0 OR T=3 THEN LET E$=STR$ S: IF T=3 THEN LET E$=E$+","+STR$ L
150 IF s=16384 AND l=6912 THEN LET E$="SCREEN$": LET D$=""
160 PRINT AT 0,10;" S A V E R ";AT 2,0;"TYPE OF FILE: ";t$;AT 4,0;"NAME OF FILE: ";n$( TO c);AT 6,0;"LENGTH OF FILE:";L;" Bytes";AT 8,0;"START OF FILE: ";S;s$
170 PRINT AT 12,0;"TO SAVE THIS FILE USE:";AT 14,0;"SAVE """;N$( TO c);""" ";D$;" ";E$
180 PRINT AT 18,0;"PRESS 'P' TO PRINT ABOVE DATA","PRESS 'H' TO LOAD ANOTHER HEADERPRESS 'S' TO SAVE THIS PROGRAM"
190 PAUSE 0: IF INKEY$="p" THEN LPRINT "SAVE """;N$( TO c);""" ";D$;" ";E$: LPRINT : LPRINT
200 IF INKEY$="h" THEN CLS : GO TO 20
210 IF INKEY$="s" THEN CLS : GO TO 240
220 GO TO 190
230 DATA "Basic Program","LINE","Numeric Array","DATA ()","String Array","DATA $ ()","Machine Code","CODE"
240 SAVE "SAVER" LINE 10: SAVE "Saver code"CODE 32768,472
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

