
**********************************************************************
files: Errors.TXT, Errors.TAP
       Trap.BAS, Trap.ASM, McTrap.ASM
**********************************************************************

** ON ERROR ... REPEAT
   ===================

Here's a very short ON ERROR routine, which returns to the line & statement causing the error. POKE the stack address pointed to by ERR_SP (23613) with the address of the routine; or with with whatever was there before (on a 48k Spectrum normally 4867 ($1303 MAIN-4)) to restore normality.

Trap.BAS [code]
9998 CLEAR 32767:
     FOR a=32768 TO 32768+17: READ b: POKE a,b: NEXT a:
     SAVE "Trap.BAS": SAVE "Trap.MC" CODE 32768,16:
     DATA 243,59,59,251,33,158,27,229,42,69,92,58,71,92,87,195,115,30
[/code]

Trap.ASM [code]
        org  32768
TRAP:   di
        dec  sp
        dec  sp              ;preserve error return on stack
        ei
        ld   hl,$1b9e        ;LINE-NEW
        push hl
        LD   HL,(23621)      ;PPC = current line
        LD   A,(23623)       ;SUBPPC = current statement
        ld   d,a
        JP   $1e73           ;GO-TO-2
[/code]

For the +2A/+3, replace "ld hl,$1b9e" with: [code]
PLUS3M: ld   hl,$1031        ;STMT-RET (+2A/+3/+3e ROM.1)
        push hl
        ld   hl,$5b2f        ;REGNUOY  (+2A/+3/+3e paging)
[/code]

Most internal errors will just loop indefinitely as the error will persist, but external errors (eg. INPUT, LOAD) can be resolved by making a valid input. Note that "0 OK" and "9 STOP statement" reports are also handled via the ROM's error routine, so if a return to BASIC is to be allowed then the trap needs to be cleared before quitting.

A more comprehensive error trap is easily handled by saving PPC / SUBPPC / ERR_NR and setting the return line & statement to jump back to a BASIC routine, from where the error handling can be tailored to the error location & type.


**********************************************************************


** ON ERROR ... GO TO
   ==================

This more comprehensive routine saves the number of the line where the error occurred and checks the Spectrum model, as the method for returning to BASIC successfully varies dependent on which ROM is installed.

McTrap.BAS [code]
     REM ENABLE ERROR TRAP
     REM olderr=any convenient address to save the original error return
9115 LET sp=PEEK 23613+256*PEEK 23614:
     POKE olderr,PEEK sp: POKE olderr+1,PEEK (sp+1):
     RANDOMIZE MCTRAP: POKE sp,PEEK 23670: POKE sp+1,PEEK 23671: RETURN
     REM DISABLE ERROR TRAP
9120 LET sp=PEEK 23613+256*PEEK 23614:
     POKE sp,PEEK olderr: POKE sp+1,PEEK olderr+1: RETURN
[/code]

McTrap.ASM [code]
        org  32768
MCTRAP: di
        dec  sp
        dec  sp              ;preserve error return on stack
        ei
MODE48: ld   hl,$1b9e        ;LINE-NEW
        bit  4,(iy+$01)
        jr   z,MCCONT
        ld   a,(19)
        inc  a               ;A =168 if +2A/+3 else 0
        ld   d,a
        ld   a,(5440)        ;A =83 if Sinclair else 65 if Amstrad
        add  a,d             ;A =83 +128k; =65 +2; =233 +2A/+3/+3e
        cp   233
        jr   nz,MCCONT
PLUS3M: ld   hl,$1031        ;STMT-RET (+2A/+3/+3e ROM.1)
        push hl
        ld   hl,$5b2f        ;REGNUOY  (+2A/+3/+3e paging)
MCCONT: push hl
        LD   HL,(23621)      ;save PPC current line
        LD   (?????),HL      ;wherever's convenient
        LD   A,(23610)       ;save ERR_NR error code
        LD   (?????),A       ;wherever's convenient
        LD   A,$ff
        LD   (23610),A       ;reset error code
        LD   HL,9000         ;line number of BASIC error handler
        ld   a,1             ;statement number
        ld   d,a
MCLOOP: CALL $1f54           ;BREAK-KEY
        JP   C,$1e73         ;GO-TO-2 - jump if not BREAK
        JR   MCLOOP          ;ignore BREAK
[/code]


**********************************************************************


** ON ERROR ... REPEAT ... all models
   ==================================

Here's the smallest comprehensive error trap for the models shown. They all preserve the error return so there's no fluking. They all jump back to STMT_R_1 in STMT_RET on BREAK, but it's in a different place in each ROM so each trap is different. As it's not likely that more than 16 streams will be open I've put the extra bit of code at the end of STRMS. Some explanatory notes follow.

[code]
[b]48[/b]
     LET sp=PEEK 23613+256*PEEK 23614: POKE sp,49: POKE sp+1,92:
     FOR a=23601 TO 23605: READ b: POKE a,b: NEXT a:
     DATA 59,59,195,125,27
[b]+128/+2[/b]
     POKE 23435,49: POKE 23436,92
     FOR a=23601 TO 23605: READ b: POKE a,b: NEXT a:
     DATA 59,59,195,42,24
[b]+2A/+3[/b]
     LET sp=PEEK 23613+256*PEEK 23614: POKE sp,49: POKE sp+1,92:
     POKE 23404,46: POKE 23405,92:
     FOR a=23598 TO 23605: READ b: POKE a,b: NEXT a:
     DATA 195,58,16,59,59,195,58,91
[/code]

[b]48[/b]
The 'sp' POKEs change the error return in ((ERR_SP)) to 23601.
The DATA at 23601 is "dec sp : dec sp : jp $1b7d".
[b]+128/+2[/b]
The first two POKEs change the error return in (SYNRET) to 23601.
The DATA at 23601 is "dec sp : dec sp : jp $182a".
[b]+2A/+3[/b]
This version has to be handled differently because the error handler does an extra +3DOS call before calling (SYNRET) and the ((ERR_SP)) entry gets overwritten before it can be preserved, so the sequence has to be changed.
The 'sp' POKEs change the error return in ((ERR_SP)) to 23601.
The DATA at 23601 is "dec sp : dec sp : jp $5b3a" (normal +2A/+3 exit).
The second two POKEs change the error return in (SYNRET) to 23598.
The DATA at 23598 is "jp $103a".


**********************************************************************
