Subversion Repositories Spectranet

[/] [branches/] [gnubinutils/] [rom/] [basicextn.asm] - Diff between revs 371 and 384

Show entire file | Details | Blame | View Log

Rev 371 Rev 384
Line 31... Line 31...
;
;
; Credits - Garry Lancaster for pointers on how the ZX error
; Credits - Garry Lancaster for pointers on how the ZX error
; handler works and some sample code.
; handler works and some sample code.
; Melbourne House for the Complete Shadow ROM disassembly, which was very
; Melbourne House for the Complete Shadow ROM disassembly, which was very
; instructive in this endeavour.
; instructive in this endeavour.
 
.include        "sysvars.inc"
 
.include        "zxrom.inc"
 
.include        "zxsysvars.inc"
 
.include        "spectranet.inc"
 
 
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
; F_addbasext: Adds a new BASIC command or extension.
; F_addbasext: Adds a new BASIC command or extension.
; Parameters: HL = pointer to info table for new command.
; Parameters: HL = pointer to info table for new command.
; The table is formatted as follows, and is 6 bytes long:
; The table is formatted as follows, and is 6 bytes long:
;  byte 0   - ZX error code that's relevant to the command
;  byte 0   - ZX error code that's relevant to the command
;  byte 1,2 - pointer to command string
;  byte 1,2 - pointer to command string
;  byte 3   - ROM page (0 if none)
;  byte 3   - ROM page (0 if none)
;  byte 4,5 - pointer to routine to call
;  byte 4,5 - pointer to routine to call
; Carry flag is set if we have run out of space.
; Carry flag is set if we have run out of space.
F_addbasicext
.text
 
.globl F_addbasicext
 
F_addbasicext:
        ld de, (v_tabletop)     ; get the current table pointer
        ld de, (v_tabletop)     ; get the current table pointer
        ld a, 0xFB              ; last byte possible
        ld a, 0xFB              ; last byte possible
        cp e
        cp e
        ret c                   ; e > a
        ret c                   ; e > a
        ld bc, 6                ; 6 bytes
        ld bc, 6                ; 6 bytes
Line 66... Line 73...
; The main RST 8 error recovery handler.
; The main RST 8 error recovery handler.
; This is jumped to when RST 8 is trapped, and looks to see if the ROM
; This is jumped to when RST 8 is trapped, and looks to see if the ROM
; has passed us something of interest.
; has passed us something of interest.
; Note that changing the Spectranet system variable 'v_rst8vector' allows
; Note that changing the Spectranet system variable 'v_rst8vector' allows
; you to completely replace this routine with something else.
; you to completely replace this routine with something else.
J_rst8handler
.globl J_rst8handler
 
J_rst8handler:
        ld a, (v_tabletop)      ; Check there's something to do
        ld a, (v_tabletop)      ; Check there's something to do
        and a                   ; if the LSB of tabletop is 0, nothing to do
        and a                   ; if the LSB of tabletop is 0, nothing to do
        jp z, J_rst8done
        jp z, J_rst8done
        ex de, hl               ; address of code is in DE
        ex de, hl               ; address of code is in DE
        rst CALLBAS
        rst CALLBAS
        defw ZX_GET_ERR         ; get the error code (which may be in ZX ROM)
        defw ZX_GET_ERR         ; get the error code (which may be in ZX ROM)
        cp 0x0B                 ; Nonsense in BASIC?
        cp 0x0B                 ; Nonsense in BASIC?
        jr z, .handled
        jr z, .handled1
;       cp 0x07                 ; End of file?
;       cp 0x07                 ; End of file?
;       jp z, J_handleeof
;       jp z, J_handleeof
        jp J_rst8done
        jp J_rst8done
.handled
.handled1:
        ld (ZX_ERR_NR), a       ; Save the error number in ZX sysvars
        ld (ZX_ERR_NR), a       ; Save the error number in ZX sysvars
        ld (v_errnr_save), a    ; and ours.
        ld (v_errnr_save), a    ; and ours.
        ld hl, (ZX_CH_ADD)      ; save current CH_ADD
        ld hl, (ZX_CH_ADD)      ; save current CH_ADD
        ld (v_chaddsave), hl
        ld (v_chaddsave), hl
        pop af                  ; discard top value of the stack
        pop af                  ; discard top value of the stack
Line 92... Line 100...
        bit 0, a                ; This is set to 1 if we are running our cmds
        bit 0, a                ; This is set to 1 if we are running our cmds
        jp nz, J_romerr         ; so we shouldn't really get here.
        jp nz, J_romerr         ; so we shouldn't really get here.
        or 1                    ; set 'our command' flag
        or 1                    ; set 'our command' flag
        ld (v_interpflags), a
        ld (v_interpflags), a
        bit 7, (iy + D_FLAGS)   ; Syntax time or runtime?
        bit 7, (iy + D_FLAGS)   ; Syntax time or runtime?
        jr nz, .runtime
        jr nz, .runtime1
        ld a, 0xFF              ; signal syntax time
        ld a, 0xFF              ; signal syntax time
        ld (ZX_PPC_HI), a
        ld (ZX_PPC_HI), a
.runtime
.runtime1:
        ld b, (iy + D_SUBPPC)   ; Statement counter
        ld b, (iy + D_SUBPPC)   ; Statement counter
        ld c, 0                 ; Quote mark counter
        ld c, 0                 ; Quote mark counter
        bit 7, (iy + D_PPC_HI)  ; Program area?
        bit 7, (iy + D_PPC_HI)  ; Program area?
        jr z, .progline
        jr z, .progline1
        push bc                 ; Save counters
        push bc                 ; Save counters
        rst CALLBAS
        rst CALLBAS
        defw ZX_E_LINE_NO       ; Call E_LINE_NO to update CH_ADD to 1st char
        defw ZX_E_LINE_NO       ; Call E_LINE_NO to update CH_ADD to 1st char
        pop bc
        pop bc
        rst CALLBAS
        rst CALLBAS
        defw ZX_GET_CHAR        ; HL=first char in line
        defw ZX_GET_CHAR        ; HL=first char in line
        jr .sstat               ; jump forward to the DJNZ
        jr .sstat1              ; jump forward to the DJNZ
        ; the following mess sorts out rewinding CH_ADD and removing
        ; the following mess sorts out rewinding CH_ADD and removing
        ; floating point values.
        ; floating point values.
.progline
.progline1:
        ld hl, (ZX_PROG)        ; get address of program
        ld hl, (ZX_PROG)        ; get address of program
.sc_l_loop
.sc_l_loop1:
        ld a, (ZX_PPC_HI)       ; compare with current line
        ld a, (ZX_PPC_HI)       ; compare with current line
        cp (hl)
        cp (hl)
        jr nc, .testlow         ; jump if <= line to be searched for
        jr nc, .testlow1                ; jump if <= line to be searched for
.nreport1
.nreport11:
        ld hl, STR_badcmd       ; Return with our equiv of nonsense in BASIC
        ld hl, STR_badcmd       ; Return with our equiv of nonsense in BASIC
        ld a, 1
        ld a, 1
        jp J_reporterr
        jp J_reporterr
.testlow
.testlow1:
        inc hl                  ; lsb of line number
        inc hl                  ; lsb of line number
        jr nz, .line_len        ; jump if current line is not the expected one
        jr nz, .line_len1       ; jump if current line is not the expected one
        ld a, (ZX_PPC_LO)       ; Compare the next byte
        ld a, (ZX_PPC_LO)       ; Compare the next byte
        cp (hl)
        cp (hl)
        jr c, .nreport1         ; Error if the line does not exist
        jr c, .nreport11                ; Error if the line does not exist
.line_len
.line_len1:
        inc hl                  ; inc the pointer
        inc hl                  ; inc the pointer
        ld e, (hl)
        ld e, (hl)
        inc hl
        inc hl
        ld d, (hl)              ; fetch length into DE
        ld d, (hl)              ; fetch length into DE
        inc hl                  ; point to the start of the line
        inc hl                  ; point to the start of the line
        jr z, .sstat            ; jump if the line is found
        jr z, .sstat1           ; jump if the line is found
        add hl, de              ; increment pointer to next line
        add hl, de              ; increment pointer to next line
        jr .sc_l_loop           ; continue until found
        jr .sc_l_loop1          ; continue until found
.skip_num
.skip_num1:
        ld de, 0x06             ; length of a float
        ld de, 0x06             ; length of a float
        add hl, de              ; skip the float
        add hl, de              ; skip the float
.each_st
.each_st1:
        ld a, (hl)              ; Get a char from the line
        ld a, (hl)              ; Get a char from the line
        cp 0x0E                 ; Number marker?
        cp 0x0E                 ; Number marker?
        jr z, .skip_num         ; Skip the number
        jr z, .skip_num1                ; Skip the number
        inc hl                  ; point to next char
        inc hl                  ; point to next char
        cp '"'                  ; Quote symbol?
        cp '"'                  ; Quote symbol?
        jr nz, .chkend          ; No
        jr nz, .chkend1         ; No
        dec c                   ; decrement " counter
        dec c                   ; decrement " counter
.chkend
.chkend1:
        cp ':'                  ; Colon?
        cp ':'                  ; Colon?
        jr z, .chkeven          ; Yes
        jr z, .chkeven1         ; Yes
        cp 0xCB                 ; THEN token?
        cp 0xCB                 ; THEN token?
        jr nz, .chkend_l
        jr nz, .chkend_l1
.chkeven
.chkeven1:
        bit 0, c                ; Even number of " chars?
        bit 0, c                ; Even number of " chars?
        jr z, .sstat            ; Jump if the statement is finished
        jr z, .sstat1           ; Jump if the statement is finished
.chkend_l
.chkend_l1:
        cp 0x80                 ; Line finished?
        cp 0x80                 ; Line finished?
        jr nz, .each_st         ; No, continue the loop
        jr nz, .each_st1                ; No, continue the loop
        jr .nreport1            ; Give an error - wrong number of quotes
        jr .nreport11           ; Give an error - wrong number of quotes
.sstat
.sstat1:
        djnz .each_st           ; Continue with next stmt
        djnz .each_st1          ; Continue with next stmt
        dec hl                  ; HL now points to start address of stmt
        dec hl                  ; HL now points to start address of stmt
        ld (ZX_CH_ADD), hl      ; store in CH_ADD
        ld (ZX_CH_ADD), hl      ; store in CH_ADD
        bit 7, (iy + D_FLAGS)   ; Checking syntax?
        bit 7, (iy + D_FLAGS)   ; Checking syntax?
        jr nz, .cl_work
        jr nz, .cl_work1
        bit 7, (iy + D_PPC_HI)  ; Give error if line is not in editing area
        bit 7, (iy + D_PPC_HI)  ; Give error if line is not in editing area
        jp z, J_err_6
        jp z, J_err_6
 
 
        ; Remove all 6 byte FP numbers put in by the ZX ROM interpreter
        ; Remove all 6 byte FP numbers put in by the ZX ROM interpreter
        dec hl                  ; balance inc below
        dec hl                  ; balance inc below
        ld c, 0                 ; clear C
        ld c, 0                 ; clear C
.rcln_num
.rcln_num1:
        inc hl                  ; Point to next char
        inc hl                  ; Point to next char
        ld a, (hl)              ; Get char
        ld a, (hl)              ; Get char
        cp 0x0E                 ; Start of a number?
        cp 0x0E                 ; Start of a number?
        jr nz, .nextnum         ; no
        jr nz, .nextnum1                ; no
        push bc                 ; save BC
        push bc                 ; save BC
        rst CALLBAS             ; call RECLAIM-2 in ZX ROM
        rst CALLBAS             ; call RECLAIM-2 in ZX ROM
        defw ZX_RECLAIM_2       ; to reclaim the number
        defw ZX_RECLAIM_2       ; to reclaim the number
        push hl                 ; save the pointer to the number
        push hl                 ; save the pointer to the number
        ld de, (v_chaddsave)    ; jp forward if the 6 bytes were
        ld de, (v_chaddsave)    ; jp forward if the 6 bytes were
        and a                   ; reclaimed after the char pointed to
        and a                   ; reclaimed after the char pointed to
        sbc hl, de              ; in the saved CH_ADD
        sbc hl, de              ; in the saved CH_ADD
        jr nc, .nxt_1
        jr nc, .nxt_11
        ex de, hl               ; otherwise update saved ch_add
        ex de, hl               ; otherwise update saved ch_add
        ld bc, 6                ; was moved 6 bytes down
        ld bc, 6                ; was moved 6 bytes down
        and a
        and a
        sbc hl, bc
        sbc hl, bc
        ld (v_chaddsave), hl    ; save the new value
        ld (v_chaddsave), hl    ; save the new value
.nxt_1
.nxt_11:
        pop hl                  ; restore pointer and counter
        pop hl                  ; restore pointer and counter
        pop bc
        pop bc
.nextnum
.nextnum1:
        ld a, (hl)              ; jump back until the line is finished
        ld a, (hl)              ; jump back until the line is finished
        cp 0x0D
        cp 0x0D
        jr nz, .rcln_num
        jr nz, .rcln_num1
.cl_work                        ; Clear workspace
.cl_work1:                      ; Clear workspace
        rst CALLBAS
        rst CALLBAS
        defw ZX_SET_WORK        ; ZX SET-WORK routine
        defw ZX_SET_WORK        ; ZX SET-WORK routine
        call F_parser           ; If this returns, command not found.
        call F_parser           ; If this returns, command not found.
J_err_6
.globl J_err_6
 
J_err_6:
        ld hl, (v_chaddsave)    ; restore initial CH_ADD
        ld hl, (v_chaddsave)    ; restore initial CH_ADD
        ld (ZX_CH_ADD), hl
        ld (ZX_CH_ADD), hl
        jp J_romerr             ; Main rom error handler
        jp J_romerr             ; Main rom error handler
 
 
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
; J_rst8done
; J_rst8done
; Early escape from RST 8 routine when we've identified the error code
; Early escape from RST 8 routine when we've identified the error code
; isn't something we're interested in. It restores the stack and restarts
; isn't something we're interested in. It restores the stack and restarts
; the ZX ROM's RST8 routine.
; the ZX ROM's RST8 routine.
J_rst8done
J_rst8done:
        ld hl, 0x000B           ; return address, after 'ld hl, (CH_ADD)'
        ld hl, 0x000B           ; return address, after 'ld hl, (CH_ADD)'
        ex (sp), hl             ; put it on the stack, discarding old value
        ex (sp), hl             ; put it on the stack, discarding old value
        ld hl, (ZX_CH_ADD)      ; 1st instruction in ZX ROM RST8 routine
        ld hl, (ZX_CH_ADD)      ; 1st instruction in ZX ROM RST8 routine
        jp UNPAGE
        jp PAGEOUT
 
 
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
; J_zxrom_exit
; J_zxrom_exit
; This exits to the BASIC ROM, resetting our private flags.
; This exits to the BASIC ROM, resetting our private flags.
; First stack entry should contain address where control should be returned.
; First stack entry should contain address where control should be returned.
J_zxrom_exit
J_zxrom_exit:
        xor a
        xor a
        ld (v_interpflags), a   ; reset our flags
        ld (v_interpflags), a   ; reset our flags
        jp UNPAGE
        jp PAGEOUT
 
 
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; F_statement_end / J_exit_success
; F_statement_end / J_exit_success
; This performs 'end of statement' actions. If the statment isn't actually
; This performs 'end of statement' actions. If the statment isn't actually
; ended it triggers the ROM error routine.
; ended it triggers the ROM error routine.
; Jumping in at J_exit_success performs the post-command actions.
; Jumping in at J_exit_success performs the post-command actions.
F_statement_end
.globl F_statement_end
 
F_statement_end:
        cp 0x0D                 ; ZX char for enter
        cp 0x0D                 ; ZX char for enter
        jr z, .synorrun         ; if so check for syntax or run time
        jr z, .synorrun2                ; if so check for syntax or run time
        cp ':'                  ; The other statement end char is :
        cp ':'                  ; The other statement end char is :
        jr z, .synorrun         ; If neither, return with 'nonsense' code
        jr z, .synorrun2                ; If neither, return with 'nonsense' code
        ld hl, STR_badcmd
        ld hl, STR_badcmd
        ld a, 1
        ld a, 1
        jp J_sherror
        jp J_sherror
.synorrun
.synorrun2:
        bit 7, (iy + D_FLAGS)   ; Syntax time or run time?
        bit 7, (iy + D_FLAGS)   ; Syntax time or run time?
        ret nz                  ; Run time - return and allow exec actions.
        ret nz                  ; Run time - return and allow exec actions.
J_exit_success
.globl J_exit_success
 
J_exit_success:
        ei                      ; ensure interrupts are enabled (else we hang)
        ei                      ; ensure interrupts are enabled (else we hang)
        ld sp, (ZX_ERR_SP)      ; restore the stack
        ld sp, (ZX_ERR_SP)      ; restore the stack
        ld (iy + D_ERR_NR), 0xFF ; clear error status
        ld (iy + D_ERR_NR), 0xFF ; clear error status
        ld hl, ZX_STMT_NEXT     ; return address in BASIC ROM
        ld hl, ZX_STMT_NEXT     ; return address in BASIC ROM
        bit 7, (iy + D_FLAGS)   ; Syntax or run time?
        bit 7, (iy + D_FLAGS)   ; Syntax or run time?
        jr z, .syntaxtime       ; Do the syntax time return action
        jr z, .syntaxtime2      ; Do the syntax time return action
        ld a, 0x7F              ; Check for BREAK - port 0x7FFE
        ld a, 0x7F              ; Check for BREAK - port 0x7FFE
        in a, (0xFE)
        in a, (0xFE)
        rra
        rra
        jr c, .runtime          ; BREAK is not being pressed
        jr c, .runtime2         ; BREAK is not being pressed
        ld a, 0xFE              ; port 0xFEFE
        ld a, 0xFE              ; port 0xFEFE
        in a, (0xFE)
        in a, (0xFE)
        jr nc, .break           ; BREAK was pressed
        jr nc, .break2          ; BREAK was pressed
.runtime
.runtime2:
        ld hl, ZX_STMT_R_1      ; ROM return address at runtime
        ld hl, ZX_STMT_R_1      ; ROM return address at runtime
.syntaxtime
.syntaxtime2:
        push hl
        push hl
        jp J_zxrom_exit         ; Page out and return to Spectrum ROM
        jp J_zxrom_exit         ; Page out and return to Spectrum ROM
.break
.break2:
        ld (iy + D_ERR_NR), 0x14 ; L - BREAK into program and fall out
        ld (iy + D_ERR_NR), 0x14 ; L - BREAK into program and fall out
                                ; via J_romerr
                                ; via J_romerr
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
; J_romerr/J_sterror
; J_romerr/J_sterror
; Exit with an error with the '?' marker set to the right place.
; Exit with an error with the '?' marker set to the right place.
; J_romerr also sets bit 3 of TV_FLAGS.
; J_romerr also sets bit 3 of TV_FLAGS.
J_romerr
J_romerr:
        res 3, (iy + D_TV_FLAG) ; mode unchanged
        res 3, (iy + D_TV_FLAG) ; mode unchanged
J_sterror
J_sterror:
        ld sp, (ZX_ERR_SP)      ; reset the stack
        ld sp, (ZX_ERR_SP)      ; reset the stack
        ld hl, (ZX_CH_ADD)      ; copy character reached
        ld hl, (ZX_CH_ADD)      ; copy character reached
        ld (ZX_X_PTR), hl       ; to the place where the ? marker should be
        ld (ZX_X_PTR), hl       ; to the place where the ? marker should be
        ld hl, ZX_SET_STK       ; return via SET_STK routine in BASIC ROM
        ld hl, ZX_SET_STK       ; return via SET_STK routine in BASIC ROM
        push hl
        push hl
Line 279... Line 290...
 
 
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; J_sherror
; J_sherror
; Exits via J_sterror if syntax checking, or falls through into
; Exits via J_sterror if syntax checking, or falls through into
; J_reporterr if not
; J_reporterr if not
J_sherror
J_sherror:
        bit 7, (iy + D_FLAGS)   ; Syntax or runtime?
        bit 7, (iy + D_FLAGS)   ; Syntax or runtime?
        jr z, J_sterror
        jr z, J_sterror
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
; J_reporterr
; J_reporterr
; Reports an error message and returns control to the ZX BASIC ROM.
; Reports an error message and returns control to the ZX BASIC ROM.
; Pass the error number in A, error string in HL.
; Pass the error number in A, error string in HL.
J_reporterr
.globl J_reporterr
 
J_reporterr:
        push hl                 ; save pointer to message
        push hl                 ; save pointer to message
        ld (ZX_ERR_NR), a       ; save the error number
        ld (ZX_ERR_NR), a       ; save the error number
        xor a                   ; clear interpreter flags
        xor a                   ; clear interpreter flags
        ld (v_interpflags), a
        ld (v_interpflags), a
        res 5, (iy + D_FLAGS)   ; ready for new key
        res 5, (iy + D_FLAGS)   ; ready for new key
Line 307... Line 319...
        rst CALLBAS
        rst CALLBAS
        defw ZX_CLS_LOWER       ; clear lower 2 lines
        defw ZX_CLS_LOWER       ; clear lower 2 lines
        set 5, (iy + D_TV_FLAG) ; set TV flags accordingly
        set 5, (iy + D_TV_FLAG) ; set TV flags accordingly
        res 3, (iy + D_TV_FLAG)
        res 3, (iy + D_TV_FLAG)
        pop hl                  ; get error string back
        pop hl                  ; get error string back
.reportloop                     ; string pointed to by HL is null terminated
.reportloop2:                   ; string pointed to by HL is null terminated
        ld a, (hl)              ; get char
        ld a, (hl)              ; get char
        and a                   ; null terminator?
        and a                   ; null terminator?
        jr z, .endreport
        jr z, .endreport2
        push hl
        push hl
        rst CALLBAS
        rst CALLBAS
        defw ZX_PRINT_A_1       ; Print the character
        defw ZX_PRINT_A_1       ; Print the character
        pop hl
        pop hl
        inc hl
        inc hl
        jr .reportloop
        jr .reportloop2
.endreport
.endreport2:
        ld sp, (ZX_ERR_SP)      ; reset stack
        ld sp, (ZX_ERR_SP)      ; reset stack
        inc sp                  ; ignore first address
        inc sp                  ; ignore first address
        inc sp
        inc sp
        ld hl, ZX_ERRMSG_RET    ; return halfway through ZX BASIC errmsg routine
        ld hl, ZX_ERRMSG_RET    ; return halfway through ZX BASIC errmsg routine
        push hl
        push hl
        jp J_zxrom_exit
        jp J_zxrom_exit
 
 
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
; Generic default error message, morally equivalent to 'Nonsense in BASIC'
; Generic default error message, morally equivalent to 'Nonsense in BASIC'
; but different so it's easy to tell we generated it.
; but different so it's easy to tell we generated it.
STR_badcmd      defb "Bad command",0
STR_badcmd:     defb "Bad command",0
 
 
;===========================================================================
;===========================================================================
; The extra command parser.
; The extra command parser.
; This uses a table (normally at 0x3A00) of vectors which point to
; This uses a table (normally at 0x3A00) of vectors which point to
; the strings defining new commands, the error code that they respond to
; the strings defining new commands, the error code that they respond to
Line 340... Line 352...
; and address of the routine that handles the command.
; and address of the routine that handles the command.
 
 
;---------------------------------------------------------------------------
;---------------------------------------------------------------------------
; F_parser
; F_parser
; A simple command parser.
; A simple command parser.
F_parser
.globl F_parser
 
F_parser:
        ld a, (v_pgb)           ; get current page B
        ld a, (v_pgb)           ; get current page B
        ld (v_origpageb), a     ; and save it
        ld (v_origpageb), a     ; and save it
        ld hl, TABLE_basext     ; start at the start of the parser's table
        ld hl, TABLE_basext     ; start at the start of the parser's table
.ploop
.ploop3:
        ld a, (hl)              ; get the error code this command responds to
        ld a, (hl)              ; get the error code this command responds to
        and a                   ; if it's zero, the table has ended
        and a                   ; if it's zero, the table has ended
        jr z, .notfound
        jr z, .notfound3
        inc hl
        inc hl
        ld e, (hl)              ; get the address of the command string
        ld e, (hl)              ; get the address of the command string
        inc hl
        inc hl
        ld d, (hl)
        ld d, (hl)
        inc hl
        inc hl
Line 361... Line 374...
        call nz, F_setpageB     ; page this page into page area B
        call nz, F_setpageB     ; page this page into page area B
        ex de, hl               ; put string address in hl
        ex de, hl               ; put string address in hl
        push de                 ; save table pointer
        push de                 ; save table pointer
        call F_pstrcmp          ; compare it with what's at CH_ADD
        call F_pstrcmp          ; compare it with what's at CH_ADD
        pop hl                  ; restore table pointer into hl
        pop hl                  ; restore table pointer into hl
        jr nz, .skip            ; skip fetching the address if no match
        jr nz, .skip3           ; skip fetching the address if no match
        ld e, (hl)              ; fetch address
        ld e, (hl)              ; fetch address
        inc hl
        inc hl
        ld d, (hl)
        ld d, (hl)
        inc hl
        inc hl
        ex de, hl
        ex de, hl
        pop de                  ; fix the stack by removing return addr
        pop de                  ; fix the stack by removing return addr
        jp (hl)                 ; jump to the address specified.
        jp (hl)                 ; jump to the address specified.
.skip
.skip3:
        inc hl
        inc hl
        inc hl
        inc hl
        jr .ploop
        jr .ploop3
.notfound
.notfound3:
        ld a, (v_origpageb)     ; restore page B
        ld a, (v_origpageb)     ; restore page B
        call F_setpageB
        call F_setpageB
        ret
        ret
 
 
;------------------------------------------------------------------------
;------------------------------------------------------------------------
; F_pstrcmp
; F_pstrcmp
; HL = pointer to string to compare
; HL = pointer to string to compare
; Returns with zero flag set if strings match.
; Returns with zero flag set if strings match.
F_pstrcmp
.globl F_pstrcmp
 
F_pstrcmp:
        ld de, (ZX_CH_ADD)
        ld de, (ZX_CH_ADD)
        inc de
        inc de
.loop
.loop4:
        ld a, (de)
        ld a, (de)
        ; is the character in the string pointed to by HL a
        ; is the character in the string pointed to by HL a
        ; null, return, colon or space - i.e. separator character?
        ; null, return, colon or space - i.e4. separator character?
        cp ' '
        cp ' '
        jr z, .match
        jr z, .match4
        cp ':'
        cp ':'
        jr z, .match
        jr z, .match4
        cp 0x0D
        cp 0x0D
        jr z, .match
        jr z, .match4
        cp (hl)                 ; does it match the target string?
        cp (hl)                 ; does it match the target string?
        inc hl                  ; yes, so match the next char
        inc hl                  ; yes, so match the next char
        inc de
        inc de
        jr z, .loop
        jr z, .loop4
        or 1                    ; make sure zero flag is not set
        or 1                    ; make sure zero flag is not set
        ret
        ret
.match
.match4:
        ld (ZX_CH_ADD), de      ; save syntax buffer pointer in CH_ADD
        ld (ZX_CH_ADD), de      ; save syntax buffer pointer in CH_ADD
        ld b, a                 ; save char
        ld b, a                 ; save char
        ; string matched so far - check it's actually ended, too.
        ; string matched so far - check it's actually ended, too.
        xor a
        xor a
        cp (hl)                 ; set zero flag if OK
        cp (hl)                 ; set zero flag if OK