[img] Tape Routines without BREAK error
 MDFS::Info.Comp.Spectrum.ProgTips.Tape.tape/htm Search  

The Spectrum ROM tape routines provide two main entry points - SA_BYTES and LD_BYTES. These two routines
check for SPACE being pressed and generate an error if pressed. It is possible to call the tape routines and have
them return instead of generate an error. Each routine starts by stacking SALD_RET which restores the border
colour, restores interrupts and generates a BREAK error if SPACE is pressed. By calling just after this is done, the
calling routine is returned to if SPACE is pressed. Annoyingly, there is no way of stopping the tape routines from
aborting when just SPACE is pressed instead of SHIFT+SPACE.

Saving data

; On entry:
;  A=block type
;  IX=start
;  DE=length
CALL &04C6       ; Call SA_BYTES+4
CALL TapeExit    ; Restore border, check SPACE, enable INTs
; On exit:
;   C    : Ok
;   NC   : SPACE pressed

Loading data

; On entry:
;  A=block type
;  IX=start
;  DE=length
;  CS=load, CC=verify
INC D
EX   AF,AF'      ; Set up flags
DEC  D
DI               ; Disable interupts
CALL &0562       ; Call LD_BYTES+12
CALL TapeExit    ; Restore border, check SPACE, enable INTs
; On exit:
;   C    : Ok
;   NC+NZ: loading error or verify error
;   NC+Z : SPACE pressed
After calling LD_BYTES+12 the SPACE key has to be checked to differentiate between a tape error and a BREAK
error. The only error SA_BYTE+4 returns is a BREAK, but the same code needs to be called to restore interupts
and the border colour.

Restore border colour

After calling the tape routines the border colour has to be restored and interrupts enabled. This code also checks the
SPACE key as LD_BYTES returns the same flags for BREAK and tape error.
.TapeExit
PUSH AF          ; Save return state
LD   A,(BORDCR)  ; Get border colour
AND  &38
RRCA
RRCA
RRCA
OUT  (&FE),A     ; Set border colour
POP  AF          ; Restore flags
EI               ; Enable interupts
RET  C           ; No error
LD   A,&7F
IN   A,(&FE)     ; Scan B-SPACE
AND  1           ; Check if SPACE pressed
RET              ; NZ=not pressed, Z=pressed

Calling from Basic

The routines return the status in the flags, when calling from Basic the only result returned is the contents of the BC
register. The code can be rewritten to be callable from Basic and return the result.

Machine code source

TapeBuffer=&5BEF
BORDCR=&5C48

.L23300:JP TapeInfo     ; TapeInfo entry
.L23303:                ; TapeLoad entry

.TapeLoad
LD   IX,(TapeBuffer+13) ; Get load address
LD   DE,(TapeBuffer+11) ; Get file length
LD   A,&FF              ; &FF=Data Block
JR   TapeCallLoad

.TapeInfo
LD   IX,TapeBuffer      ; IX=>buffer for header
LD   DE,17              ; DE=header length
XOR  A                  ; &00=Header block
; Fall through into TapeCallLoad

.TapeCallLoad
; A =block type
; IX=start
; DE=length
SCF              ; CS=load
INC  D           ; Make D non-zero
EX   AF,AF'      ; Set up flags
DEC  D           ; Restore D
DI               ; Disable interupts
CALL &0562       ; Call LD_BYTES+12
; Fall through into TapeExit, restore border, check SPACE, enable INTs

.TapeExit
PUSH AF          ; Save return state
LD   A,(BORDCR)  ; Get border colour
AND  &38
RRCA
RRCA
RRCA
OUT  (&FE),A     ; Set border colour
POP  AF          ; Restore flags
EI               ; Enable interupts
LD   BC,0
RET  C           ; No error, BC=0
LD   A,&7F
IN   A,(&FE)     ; Scan B-SPACE
RRCA             ; Move SPACE into Carry
RLC  C           ; C=00 or 01
INC  C           ; C=01 or 02
RET
; On exit,
; BC=00 - Ok
; BC=01 - SPACE pressed
; BC=02 - Tape error

In Basic

REM Create the machine code:
FOR a=23300 TO 23356:READ b:POKE a,b:NEXT a
DATA 195,19,91,221,42,252,91,237,91,250,91,62,255,24,8,221,33,239,91
DATA 17,17,0,175,55,20,8,21,243,205,98,5,245,58,72,92,230,56,15,15,15
DATA 211,254,241,251,1,0,0,216,62,127,219,254,15,203,1,12,201

REM Load the next file header to 23535-23551:
LET bc=USR 23300

REM Load next data block its own address:
LET bc=USR 23303

REM Load next data block to address 'start':
POKE 23549,INT(start/256)
POKE 23548,start-256*PEEK23549
LET bc=USR 23303

REM On return from calls:
REM bc=0 - Ok
REM bc=1 - BREAK
REM bc=2 - Tape error

Best viewed with Any Browser Valid HTML 4.0! Authored by J.G.Harston
Last update: 19-Nov-2019