CPU-Z80-Disassembler
view release on metacpan or search on metacpan
t/data/zx48_base.asm view on Meta::CPAN
; above. The position of the error will be apparent when the lower screen is
; reprinted. If no error then the re-iteration is to ED-LOOP below when
; input is arriving from the keyboard.
;; ED-LOOP
ED_LOOP:
call WAIT_KEY ; routine WAIT-KEY gets key possibly
; changing the mode.
push af ; save key.
ld d,0x00 ; and give a short click based
ld e,(iy-0x01) ; on PIP value for duration.
ld hl,0x00C8 ; and pitch.
call BEEPER ; routine BEEPER gives click - effective
; with rubber keyboard.
pop af ; get saved key value.
ld hl,ED_LOOP ; address: ED-LOOP is loaded to HL.
push hl ; and pushed onto stack.
; At this point there is a looping return address on the stack, an error
; handler and an input stream set up to supply characters.
; The character that has been received can now be processed.
cp 0x18 ; range 24 to 255 ?
jr nc,ADD_CHAR ; forward to ADD-CHAR if so.
cp 0x07 ; lower than 7 ?
jr c,ADD_CHAR ; forward to ADD-CHAR also.
; Note. This is a 'bug' and chr$ 6, the comma
; control character, should have had an
; entry in the ED-KEYS table.
; Steven Vickers, 1984, Pitman.
cp 0x10 ; less than 16 ?
jr c,ED_KEYS ; forward to ED-KEYS if editing control
; range 7 to 15 dealt with by a table
ld bc,0x0002 ; prepare for ink/paper etc.
ld d,a ; save character in D
cp 0x16 ; is it ink/paper/bright etc. ?
jr c,ED_CONTR ; forward to ED-CONTR if so
; leaves 22d AT and 23d TAB
; which can't be entered via KEY-INPUT.
; so this code is never normally executed
; when the keyboard is used for input.
inc bc ; if it was AT/TAB - 3 locations required
bit 7,(iy+0x37) ; test FLAGX - Is this INPUT LINE ?
jp z,ED_IGNORE ; jump to ED-IGNORE if not, else
call WAIT_KEY ; routine WAIT-KEY - input address is KEY-NEXT
; but is reset to KEY-INPUT
ld e,a ; save first in E
;; ED-CONTR
ED_CONTR:
call WAIT_KEY ; routine WAIT-KEY for control.
; input address will be key-next.
push de ; saved code/parameters
ld hl,(0x5C5B) ; fetch address of keyboard cursor from K_CUR
res 0,(iy+0x07) ; set MODE to 'L'
call MAKE_ROOM ; routine MAKE-ROOM makes 2/3 spaces at cursor
pop bc ; restore code/parameters
inc hl ; address first location
ld (hl),b ; place code (ink etc.)
inc hl ; address next
ld (hl),c ; place possible parameter. If only one
; then DE points to this location also.
jr ADD_CH_1 ; forward to ADD-CH-1
; ------------------------
; Add code to current line
; ------------------------
; this is the branch used to add normal non-control characters
; with ED-LOOP as the stacked return address.
; it is also the OUTPUT service routine for system channel 'R'.
;; ADD-CHAR
ADD_CHAR:
res 0,(iy+0x07) ; set MODE to 'L'
X0F85:
ld hl,(0x5C5B) ; fetch address of keyboard cursor from K_CUR
call ONE_SPACE ; routine ONE-SPACE creates one space.
; either a continuation of above or from ED-CONTR with ED-LOOP on stack.
;; ADD-CH-1
ADD_CH_1:
ld (de),a ; load current character to last new location.
inc de ; address next
ld (0x5C5B),de ; and update K_CUR system variable.
ret ; return - either a simple return
; from ADD-CHAR or to ED-LOOP on stack.
; ---
; a branch of the editing loop to deal with control characters
; using a look-up table.
;; ED-KEYS
ED_KEYS:
ld e,a ; character to E.
ld d,0x00 ; prepare to add.
ld hl,ed_keys_t - 7 ; base address of editing keys table. $0F99
add hl,de ; add E
ld e,(hl) ; fetch offset to E
add hl,de ; add offset for address of handling routine.
push hl ; push the address on machine stack.
ld hl,(0x5C5B) ; load address of cursor from K_CUR.
ret ; Make an indirect jump forward to routine.
; ------------------
; Editing keys table
; ------------------
; For each code in the range $07 to $0F this table contains a
; single offset byte to the routine that services that code.
; Note. for what was intended there should also have been an
; entry for chr$ 6 with offset to ed-symbol.
;; ed-keys-t
ed_keys_t:
defb ED_EDIT - $ ; 07d offset $09 to Address: ED-EDIT
defb ED_LEFT - $ ; 08d offset $66 to Address: ED-LEFT
defb ED_RIGHT - $ ; 09d offset $6A to Address: ED-RIGHT
defb ED_DOWN - $ ; 10d offset $50 to Address: ED-DOWN
defb ED_UP - $ ; 11d offset $B5 to Address: ED-UP
defb ED_DELETE - $ ; 12d offset $70 to Address: ED-DELETE
defb ED_ENTER - $ ; 13d offset $7E to Address: ED-ENTER
defb ED_SYMBOL - $ ; 14d offset $CF to Address: ED-SYMBOL
defb ED_GRAPH - $ ; 15d offset $D4 to Address: ED-GRAPH
; ---------------
; Handle EDIT key
; ---------------
; The user has pressed SHIFT 1 to bring edit line down to bottom of screen.
; Alternatively the user wishes to clear the input buffer and start again.
; Alternatively ...
;; ED-EDIT
ED_EDIT:
ld hl,(0x5C49) ; fetch E_PPC the last line number entered.
; Note. may not exist and may follow program.
bit 5,(iy+0x37) ; test FLAGX - input mode ?
jp nz,CLEAR_SP ; jump forward to CLEAR-SP if not in editor.
call LINE_ADDR ; routine LINE-ADDR to find address of line
; or following line if it doesn't exist.
call LINE_NO ; routine LINE-NO will get line number from
; address or previous line if at end-marker.
ld a,d ; if there is no program then DE will
or e ; contain zero so test for this.
jp z,CLEAR_SP ; jump to CLEAR-SP if so.
; Note. at this point we have a validated line number, not just an
; approximation and it would be best to update E_PPC with the true
; cursor line value which would enable the line cursor to be suppressed
; in all situations - see shortly.
push hl ; save address of line.
inc hl ; address low byte of length.
ld c,(hl) ; transfer to C
inc hl ; next to high byte
ld b,(hl) ; transfer to B.
ld hl,0x000A ; an overhead of ten bytes
add hl,bc ; is added to length.
ld b,h ; transfer adjusted value
ld c,l ; to BC register.
call TEST_ROOM ; routine TEST-ROOM checks free memory.
call CLEAR_SP ; routine CLEAR-SP clears editing area.
ld hl,(0x5C51) ; address CURCHL
ex (sp),hl ; swap with line address on stack
push hl ; save line address underneath
ld a,0xFF ; select system channel 'R'
call CHAN_OPEN ; routine CHAN-OPEN opens it
pop hl ; drop line address
dec hl ; make it point to first byte of line num.
dec (iy+0x0F) ; decrease E_PPC_lo to suppress line cursor.
; Note. ineffective when E_PPC is one
; greater than last line of program perhaps
; as a result of a delete.
; credit. Paul Harrison 1982.
call OUT_LINE ; routine OUT-LINE outputs the BASIC line
; to the editing area.
inc (iy+0x0F) ; restore E_PPC_lo to the previous value.
ld hl,(0x5C59) ; address E_LINE in editing area.
inc hl ; advance
inc hl ; past space
inc hl ; and digit characters
inc hl ; of line number.
ld (0x5C5B),hl ; update K_CUR to address start of BASIC.
pop hl ; restore the address of CURCHL.
call CHAN_FLAG ; routine CHAN-FLAG sets flags for it.
ret ; RETURN to ED-LOOP.
; -------------------
; Cursor down editing
; -------------------
; The BASIC lines are displayed at the top of the screen and the user
; wishes to move the cursor down one line in edit mode.
; With INPUT LINE, this key must be used instead of entering STOP.
;; ED-DOWN
ED_DOWN:
bit 5,(iy+0x37) ; test FLAGX - Input Mode ?
jr nz,ED_STOP ; skip to ED-STOP if so
ld hl,0x5C49 ; address E_PPC - 'current line'
call LN_FETCH ; routine LN-FETCH fetches number of next
; line or same if at end of program.
jr ED_LIST ; forward to ED-LIST to produce an
; automatic listing.
; ---
;; ED-STOP
ED_STOP:
ld (iy+0x00),0x10 ; set ERR_NR to 'STOP in INPUT' code
jr ED_ENTER ; forward to ED-ENTER to produce error.
; -------------------
; Cursor left editing
; -------------------
; This acts on the cursor in the lower section of the screen in both
; editing and input mode.
;; ED-LEFT
ED_LEFT:
call ED_EDGE ; routine ED-EDGE moves left if possible
jr ED_CUR ; forward to ED-CUR to update K-CUR
; and return to ED-LOOP.
; --------------------
; Cursor right editing
; --------------------
; This acts on the cursor in the lower screen in both editing and input
; mode and moves it to the right.
;; ED-RIGHT
ED_RIGHT:
ld a,(hl) ; fetch addressed character.
cp 0x0D ; is it carriage return ?
ret z ; return if so to ED-LOOP
inc hl ; address next character
;; ED-CUR
ED_CUR:
ld (0x5C5B),hl ; update K_CUR system variable
ret ; return to ED-LOOP
; --------------
; DELETE editing
; --------------
; This acts on the lower screen and deletes the character to left of
; cursor. If control characters are present these are deleted first
; leaving the naked parameter (0-7) which appears as a '?' except in the
; case of chr$ 6 which is the comma control character. It is not mandatory
; to delete these second characters.
;; ED-DELETE
ED_DELETE:
call ED_EDGE ; routine ED-EDGE moves cursor to left.
ld bc,0x0001 ; of character to be deleted.
jp RECLAIM_2 ; to RECLAIM-2 reclaim the character.
; ------------------------------------------
; Ignore next 2 codes from key-input routine
; ------------------------------------------
; Since AT and TAB cannot be entered this point is never reached
; from the keyboard. If inputting from a tape device or network then
; the control and two following characters are ignored and processing
; continues as if a carriage return had been received.
; Here, perhaps, another Spectrum has said print #15; AT 0,0; "This is yellow"
; and this one is interpreting input #15; a$.
;; ED-IGNORE
ED_IGNORE:
call WAIT_KEY ; routine WAIT-KEY to ignore keystroke.
call WAIT_KEY ; routine WAIT-KEY to ignore next key.
; -------------
; Enter/newline
; -------------
; The enter key has been pressed to have BASIC line or input accepted.
;; ED-ENTER
ED_ENTER:
pop hl ; discard address ED-LOOP
pop hl ; drop address ED-ERROR
;; ED-END
ED_END:
pop hl ; the previous value of ERR_SP
ld (0x5C3D),hl ; is restored to ERR_SP system variable
bit 7,(iy+0x00) ; is ERR_NR $FF (= 'OK') ?
ret nz ; return if so
ld sp,hl ; else put error routine on stack
ret ; and make an indirect jump to it.
; -----------------------------
; Move cursor left when editing
; -----------------------------
; This routine moves the cursor left. The complication is that it must
; not position the cursor between control codes and their parameters.
; It is further complicated in that it deals with TAB and AT characters
; which are never present from the keyboard.
; The method is to advance from the beginning of the line each time,
; jumping one, two, or three characters as necessary saving the original
; position at each jump in DE. Once it arrives at the cursor then the next
; legitimate leftmost position is in DE.
;; ED-EDGE
ED_EDGE:
scf ; carry flag must be set to call the nested
call SET_DE ; subroutine SET-DE.
; if input then DE=WORKSP
; if editing then DE=E_LINE
sbc hl,de ; subtract address from start of line
add hl,de ; and add back.
inc hl ; adjust for carry.
pop bc ; drop return address
ret c ; return to ED-LOOP if already at left
; of line.
push bc ; resave return address - ED-LOOP.
ld b,h ; transfer HL - cursor address
ld c,l ; to BC register pair.
; at this point DE addresses start of line.
;; ED-EDGE-1
ED_EDGE_1:
ld h,d ; transfer DE - leftmost pointer
ld l,e ; to HL
inc hl ; address next leftmost character to
; advance position each time.
ld a,(de) ; pick up previous in A
and 0xF0 ; lose the low bits
cp 0x10 ; is it INK to TAB $10-$1F ?
; that is, is it followed by a parameter ?
jr nz,ED_EDGE_2 ; to ED-EDGE-2 if not
; HL has been incremented once
inc hl ; address next as at least one parameter.
; in fact since 'tab' and 'at' cannot be entered the next section seems
; superfluous.
; The test will always fail and the jump to ED-EDGE-2 will be taken.
ld a,(de) ; reload leftmost character
sub 0x17 ; decimal 23 ('tab')
adc a,0x00 ; will be 0 for 'tab' and 'at'.
jr nz,ED_EDGE_2 ; forward to ED-EDGE-2 if not
; HL has been incremented twice
inc hl ; increment a third time for 'at'/'tab'
;; ED-EDGE-2
ED_EDGE_2:
and a ; prepare for true subtraction
sbc hl,bc ; subtract cursor address from pointer
add hl,bc ; and add back
; Note when HL matches the cursor position BC,
; there is no carry and the previous
; position is in DE.
ex de,hl ; transfer result to DE if looping again.
; transfer DE to HL to be used as K-CUR
; if exiting loop.
jr c,ED_EDGE_1 ; back to ED-EDGE-1 if cursor not matched.
ret ; return.
; -----------------
; Cursor up editing
; -----------------
; The main screen displays part of the BASIC program and the user wishes
; to move up one line scrolling if necessary.
; This has no alternative use in input mode.
;; ED-UP
ED_UP:
bit 5,(iy+0x37) ; test FLAGX - input mode ?
ret nz ; return if not in editor - to ED-LOOP.
ld hl,(0x5C49) ; get current line from E_PPC
call LINE_ADDR ; routine LINE-ADDR gets address
ex de,hl ; and previous in DE
call LINE_NO ; routine LINE-NO gets prev line number
ld hl,0x5C4A ; set HL to E_PPC_hi as next routine stores
; top first.
call LN_STORE ; routine LN-STORE loads DE value to HL
; high byte first - E_PPC_lo takes E
; this branch is also taken from ed-down.
;; ED-LIST
ED_LIST:
call AUTO_LIST ; routine AUTO-LIST lists to upper screen
; including adjusted current line.
ld a,0x00 ; select lower screen again
jp CHAN_OPEN ; exit via CHAN-OPEN to ED-LOOP
; --------------------------------
; Use of symbol and graphics codes
; --------------------------------
; These will not be encountered with the keyboard but would be handled
; otherwise as follows.
; As noted earlier, Vickers says there should have been an entry in
; the KEYS table for chr$ 6 which also pointed here.
; If, for simplicity, two Spectrums were both using #15 as a bi-directional
; channel connected to each other:-
; then when the other Spectrum has said PRINT #15; x, y
; input #15; i ; j would treat the comma control as a newline and the
; control would skip to input j.
; You can get round the missing chr$ 6 handler by sending multiple print
; items separated by a newline '.
; chr$14 would have the same functionality.
; This is chr$ 14.
;; ED-SYMBOL
ED_SYMBOL:
bit 7,(iy+0x37) ; test FLAGX - is this INPUT LINE ?
jr z,ED_ENTER ; back to ED-ENTER if not to treat as if
; enter had been pressed.
; else continue and add code to buffer.
; Next is chr$ 15
; Note that ADD-CHAR precedes the table so we can't offset to it directly.
t/data/zx48_base.asm view on Meta::CPAN
set 3,(iy+0x02) ; update TV_FLAG - show key state has changed
cp a ; clear carry and reset zero flags -
; no actual key returned.
ret ; make the return.
; ---
; now deal with colour controls - 16-23 ink, 24-31 paper
;; KEY-CONTR
KEY_CONTR:
ld b,a ; make a copy of character.
and 0x07 ; mask to leave bits 0-7
ld c,a ; and store in C.
ld a,0x10 ; initialize to 16d - INK.
bit 3,b ; was it paper ?
jr nz,KEY_DATA ; forward to KEY-DATA with INK 16d and
; colour in C.
inc a ; else change from INK to PAPER (17d) if so.
;; KEY-DATA
KEY_DATA:
ld (iy-0x2D),c ; put the colour (0-7)/state(0/1) in KDATA
ld de,KEY_NEXT ; address: KEY-NEXT will be next input stream
jr KEY_CHAN ; forward to KEY-CHAN to change it ...
; ---
; ... so that INPUT_AD directs control to here at next call to WAIT-KEY
;; KEY-NEXT
KEY_NEXT:
ld a,(0x5C0D) ; pick up the parameter stored in KDATA.
ld de,KEY_INPUT ; address: KEY-INPUT will be next input stream
; continue to restore default channel and
; make a return with the control code.
;; KEY-CHAN
KEY_CHAN:
ld hl,(0x5C4F) ; address start of CHANNELS area using CHANS
; system variable.
; Note. One might have expected CURCHL to
; have been used.
inc hl ; step over the
inc hl ; output address
ld (hl),e ; and update the input
inc hl ; routine address for
ld (hl),d ; the next call to WAIT-KEY.
;; KEY-DONE2
KEY_DONE2:
scf ; set carry flag to show a key has been found
ret ; and return.
; --------------------
; Lower screen copying
; --------------------
; This subroutine is called whenever the line in the editing area or
; input workspace is required to be printed to the lower screen.
; It is by calling this routine after any change that the cursor, for
; instance, appears to move to the left.
; Remember the edit line will contain characters and tokens
; e.g. "1000 LET a=1" is 8 characters.
;; ED-COPY
ED_COPY:
call TEMPS ; routine TEMPS sets temporary attributes.
res 3,(iy+0x02) ; update TV_FLAG - signal no change in mode
res 5,(iy+0x02) ; update TV_FLAG - signal don't clear lower
; screen.
ld hl,(0x5C8A) ; fetch SPOSNL
push hl ; and save on stack.
ld hl,(0x5C3D) ; fetch ERR_SP
push hl ; and save also
ld hl,ED_FULL ; address: ED-FULL
push hl ; is pushed as the error routine
ld (0x5C3D),sp ; and ERR_SP made to point to it.
ld hl,(0x5C82) ; fetch ECHO_E
push hl ; and push also
scf ; set carry flag to control SET-DE
call SET_DE ; call routine SET-DE
; if in input DE = WORKSP
; if in edit DE = E_LINE
ex de,hl ; start address to HL
call OUT_LINE2 ; routine OUT-LINE2 outputs entire line up to
; carriage return including initial
; characterized line number when present.
ex de,hl ; transfer new address to DE
call OUT_CURS ; routine OUT-CURS considers a
; terminating cursor.
ld hl,(0x5C8A) ; fetch updated SPOSNL
ex (sp),hl ; exchange with ECHO_E on stack
ex de,hl ; transfer ECHO_E to DE
call TEMPS ; routine TEMPS to re-set attributes
; if altered.
; the lower screen was not cleared, at the outset, so if deleting then old
; text from a previous print may follow this line and requires blanking.
;; ED-BLANK
ED_BLANK:
ld a,(0x5C8B) ; fetch SPOSNL_hi is current line
sub d ; compare with old
jr c,ED_C_DONE ; forward to ED-C-DONE if no blanking
jr nz,ED_SPACES ; forward to ED-SPACES if line has changed
ld a,e ; old column to A
sub (iy+0x50) ; subtract new in SPOSNL_lo
jr nc,ED_C_DONE ; forward to ED-C-DONE if no backfilling.
;; ED-SPACES
ED_SPACES:
ld a,0x20 ; prepare a space.
push de ; save old line/column.
call PRINT_OUT ; routine PRINT-OUT prints a space over
; any text from previous print.
; Note. Since the blanking only occurs when
; using $09F4 to print to the lower screen,
; there is no need to vector via a RST 10
; and we can use this alternate set.
pop de ; restore the old line column.
jr ED_BLANK ; back to ED-BLANK until all old text blanked.
; -------------------------------
; THE 'EDITOR-FULL' ERROR ROUTINE
; -------------------------------
; This is the error routine addressed by ERR_SP. This is not for the out of
; memory situation as we're just printing. The pitch and duration are exactly
; the same as used by ED-ERROR from which this has been augmented. The
; situation is that the lower screen is full and a rasp is given to suggest
; that this is perhaps not the best idea you've had that day.
;; ED-FULL
ED_FULL:
ld d,0x00 ; prepare to moan.
ld e,(iy-0x02) ; fetch RASP value.
ld hl,0x1A90 ; set pitch or tone period.
call BEEPER ; routine BEEPER.
ld (iy+0x00),0xFF ; clear ERR_NR.
ld de,(0x5C8A) ; fetch SPOSNL.
jr ED_C_END ; forward to ED-C-END
; -------
; the exit point from line printing continues here.
t/data/zx48_base.asm view on Meta::CPAN
;; LINE-ZERO
LINE_ZERO:
defb 0x00, 0x00 ; dummy line number used for direct commands
;; LINE-NO-A
LINE_NO_A:
ex de,hl ; fetch the previous line to HL and set
ld de,LINE_ZERO ; DE to LINE-ZERO should HL also fail.
; -> The Entry Point.
;; LINE-NO
LINE_NO:
ld a,(hl) ; fetch the high byte - max $2F
and 0xC0 ; mask off the invalid bits.
jr nz,LINE_NO_A ; to LINE-NO-A if an end-marker.
ld d,(hl) ; reload the high byte.
inc hl ; advance address.
ld e,(hl) ; pick up the low byte.
ret ; return from here.
; -------------------
; Handle reserve room
; -------------------
; This is a continuation of the restart BC-SPACES
;; RESERVE
RESERVE:
ld hl,(0x5C63) ; STKBOT first location of calculator stack
dec hl ; make one less than new location
call MAKE_ROOM ; routine MAKE-ROOM creates the room.
inc hl ; address the first new location
inc hl ; advance to second
pop bc ; restore old WORKSP
ld (0x5C61),bc ; system variable WORKSP was perhaps
; changed by POINTERS routine.
pop bc ; restore count for return value.
ex de,hl ; switch. DE = location after first new space
inc hl ; HL now location after new space
ret ; return.
; ---------------------------
; Clear various editing areas
; ---------------------------
; This routine sets the editing area, workspace and calculator stack
; to their minimum configurations as at initialization and indeed this
; routine could have been relied on to perform that task.
; This routine uses HL only and returns with that register holding
; WORKSP/STKBOT/STKEND though no use is made of this. The routines also
; reset MEM to its usual place in the systems variable area should it
; have been relocated to a FOR-NEXT variable. The main entry point
; SET-MIN is called at the start of the MAIN-EXEC loop and prior to
; displaying an error.
;; SET-MIN
SET_MIN:
ld hl,(0x5C59) ; fetch E_LINE
ld (hl),0x0D ; insert carriage return
ld (0x5C5B),hl ; make K_CUR keyboard cursor point there.
inc hl ; next location
ld (hl),0x80 ; holds end-marker $80
inc hl ; next location becomes
ld (0x5C61),hl ; start of WORKSP
; This entry point is used prior to input and prior to the execution,
; or parsing, of each statement.
;; SET-WORK
SET_WORK:
ld hl,(0x5C61) ; fetch WORKSP value
ld (0x5C63),hl ; and place in STKBOT
; This entry point is used to move the stack back to its normal place
; after temporary relocation during line entry and also from ERROR-3
;; SET-STK
SET_STK:
ld hl,(0x5C63) ; fetch STKBOT value
ld (0x5C65),hl ; and place in STKEND.
push hl ; perhaps an obsolete entry point.
ld hl,0x5C92 ; normal location of MEM-0
ld (0x5C68),hl ; is restored to system variable MEM.
pop hl ; saved value not required.
ret ; return.
; ------------------
; Reclaim edit-line?
; ------------------
; This seems to be legacy code from the ZX80/ZX81 as it is
; not used in this ROM.
; That task, in fact, is performed here by the dual-area routine CLEAR-SP.
; This routine is designed to deal with something that is known to be in the
; edit buffer and not workspace.
; On entry, HL must point to the end of the something to be deleted.
;; REC-EDIT
REC_EDIT:
ld de,(0x5C59) ; fetch start of edit line from E_LINE.
jp RECLAIM_1 ; jump forward to RECLAIM-1.
; --------------------------
; The Table INDEXING routine
; --------------------------
; This routine is used to search two-byte hash tables for a character
; held in C, returning the address of the following offset byte.
; if it is known that the character is in the table e.g. for priorities,
; then the table requires no zero end-marker. If this is not known at the
; outset then a zero end-marker is required and carry is set to signal
; success.
;; INDEXER-1
INDEXER_1:
inc hl ; address the next pair of values.
; -> The Entry Point.
;; INDEXER
INDEXER:
t/data/zx48_base.asm view on Meta::CPAN
ld h,a ; transfer the modified
ld l,c ; line number to HL.
ld (0x5C49),hl ; update E_PPC to new line number.
call LINE_ADDR ; routine LINE-ADDR gets the address of the
; line.
; This routine is called from AUTO-LIST
;; LIST-ALL
LIST_ALL:
ld e,0x01 ; signal current line not yet printed
;; LIST-ALL-2
LIST_ALL_2:
call OUT_LINE ; routine OUT-LINE outputs a BASIC line
; using PRINT-OUT and makes an early return
; when no more lines to print. >>>
rst 0x10 ; PRINT-A prints the carriage return (in A)
bit 4,(iy+0x02) ; test TV_FLAG - automatic listing ?
jr z,LIST_ALL_2 ; back to LIST-ALL-2 if not
; (loop exit is via OUT-LINE)
; continue here if an automatic listing required.
ld a,(0x5C6B) ; fetch DF_SZ lower display file size.
sub (iy+0x4F) ; subtract S_POSN_hi ithe current line number.
jr nz,LIST_ALL_2 ; back to LIST-ALL-2 if upper screen not full.
xor e ; A contains zero, E contains one if the
; current edit line has not been printed
; or zero if it has (from OUT-LINE).
ret z ; return if the screen is full and the line
; has been printed.
; continue with automatic listings if the screen is full and the current
; edit line is missing. OUT-LINE will scroll automatically.
push hl ; save the pointer address.
push de ; save the E flag.
ld hl,0x5C6C ; fetch S_TOP the rough estimate.
call LN_FETCH ; routine LN-FETCH updates S_TOP with
; the number of the next line.
pop de ; restore the E flag.
pop hl ; restore the address of the next line.
jr LIST_ALL_2 ; back to LIST-ALL-2.
; ------------------------
; Print a whole BASIC line
; ------------------------
; This routine prints a whole BASIC line and it is called
; from LIST-ALL to output the line to current channel
; and from ED-EDIT to 'sprint' the line to the edit buffer.
;; OUT-LINE
OUT_LINE:
ld bc,(0x5C49) ; fetch E_PPC the current line which may be
; unchecked and not exist.
call CP_LINES ; routine CP-LINES finds match or line after.
ld d,0x3E ; prepare cursor '>' in D.
jr z,OUT_LINE1 ; to OUT-LINE1 if matched or line after.
ld de,0x0000 ; put zero in D, to suppress line cursor.
rl e ; pick up carry in E if line before current
; leave E zero if same or after.
;; OUT-LINE1
OUT_LINE1:
ld (iy+0x2D),e ; save flag in BREG which is spare.
ld a,(hl) ; get high byte of line number.
cp 0x40 ; is it too high ($2F is maximum possible) ?
pop bc ; drop the return address and
ret nc ; make an early return if so >>>
push bc ; save return address
call OUT_NUM_2 ; routine OUT-NUM-2 to print addressed number
; with leading space.
inc hl ; skip low number byte.
inc hl ; and the two
inc hl ; length bytes.
res 0,(iy+0x01) ; update FLAGS - signal leading space required.
ld a,d ; fetch the cursor.
and a ; test for zero.
jr z,OUT_LINE3 ; to OUT-LINE3 if zero.
rst 0x10 ; PRINT-A prints '>' the current line cursor.
; this entry point is called from ED-COPY
;; OUT-LINE2
OUT_LINE2:
set 0,(iy+0x01) ; update FLAGS - suppress leading space.
;; OUT-LINE3
OUT_LINE3:
push de ; save flag E for a return value.
ex de,hl ; save HL address in DE.
res 2,(iy+0x30) ; update FLAGS2 - signal NOT in QUOTES.
ld hl,0x5C3B ; point to FLAGS.
res 2,(hl) ; signal 'K' mode. (starts before keyword)
bit 5,(iy+0x37) ; test FLAGX - input mode ?
jr z,OUT_LINE4 ; forward to OUT-LINE4 if not.
set 2,(hl) ; signal 'L' mode. (used for input)
;; OUT-LINE4
OUT_LINE4:
ld hl,(0x5C5F) ; fetch X_PTR - possibly the error pointer
; address.
and a ; clear the carry flag.
sbc hl,de ; test if an error address has been reached.
jr nz,OUT_LINE5 ; forward to OUT-LINE5 if not.
ld a,0x3F ; load A with '?' the error marker.
call OUT_FLASH ; routine OUT-FLASH to print flashing marker.
;; OUT-LINE5
OUT_LINE5:
call OUT_CURS ; routine OUT-CURS will print the cursor if
; this is the right position.
ex de,hl ; restore address pointer to HL.
ld a,(hl) ; fetch the addressed character.
call NUMBER ; routine NUMBER skips a hidden floating
; point number if present.
inc hl ; now increment the pointer.
cp 0x0D ; is character end-of-line ?
jr z,OUT_LINE6 ; to OUT-LINE6, if so, as line is finished.
ex de,hl ; save the pointer in DE.
call OUT_CHAR ; routine OUT-CHAR to output character/token.
jr OUT_LINE4 ; back to OUT-LINE4 until entire line is done.
; ---
;; OUT-LINE6
OUT_LINE6:
pop de ; bring back the flag E, zero if current
; line printed else 1 if still to print.
ret ; return with A holding $0D
; -------------------------
; Check for a number marker
; -------------------------
; this subroutine is called from two processes. while outputting BASIC lines
; and while searching statements within a BASIC line.
; during both, this routine will pass over an invisible number indicator
; and the five bytes floating-point number that follows it.
; Note that this causes floating point numbers to be stripped from
; the BASIC line when it is fetched to the edit buffer by OUT_LINE.
; the number marker also appears after the arguments of a DEF FN statement
; and may mask old 5-byte string parameters.
;; NUMBER
NUMBER:
cp 0x0E ; character fourteen ?
ret nz ; return if not.
inc hl ; skip the character
inc hl ; and five bytes
inc hl ; following.
inc hl
inc hl
inc hl
ld a,(hl) ; fetch the following character
ret ; for return value.
; --------------------------
; Print a flashing character
; --------------------------
; This subroutine is called from OUT-LINE to print a flashing error
; marker '?' or from the next routine to print a flashing cursor e.g. 'L'.
; However, this only gets called from OUT-LINE when printing the edit line
; or the input buffer to the lower screen so a direct call to $09F4 can
; be used, even though out-line outputs to other streams.
; In fact the alternate set is used for the whole routine.
;; OUT-FLASH
OUT_FLASH:
exx ; switch in alternate set
ld hl,(0x5C8F) ; fetch L = ATTR_T, H = MASK-T
push hl ; save masks.
res 7,h ; reset flash mask bit so active.
set 7,l ; make attribute FLASH.
ld (0x5C8F),hl ; resave ATTR_T and MASK-T
ld hl,0x5C91 ; address P_FLAG
ld d,(hl) ; fetch to D
push de ; and save.
ld (hl),0x00 ; clear inverse, over, ink/paper 9
call PRINT_OUT ; routine PRINT-OUT outputs character
; without the need to vector via RST 10.
pop hl ; pop P_FLAG to H.
ld (iy+0x57),h ; and restore system variable P_FLAG.
pop hl ; restore temporary masks
ld (0x5C8F),hl ; and restore system variables ATTR_T/MASK_T
exx ; switch back to main set
ret ; return
; ----------------
; Print the cursor
; ----------------
; This routine is called before any character is output while outputting
; a BASIC line or the input buffer. This includes listing to a printer
; or screen, copying a BASIC line to the edit buffer and printing the
; input buffer or edit buffer to the lower screen. It is only in the
; latter two cases that it has any relevance and in the last case it
; performs another very important function also.
;; OUT-CURS
OUT_CURS:
ld hl,(0x5C5B) ; fetch K_CUR the current cursor address
and a ; prepare for true subtraction.
sbc hl,de ; test against pointer address in DE and
ret nz ; return if not at exact position.
; the value of MODE, maintained by KEY-INPUT, is tested and if non-zero
; then this value 'E' or 'G' will take precedence.
ld a,(0x5C41) ; fetch MODE 0='KLC', 1='E', 2='G'.
rlc a ; double the value and set flags.
jr z,OUT_C_1 ; to OUT-C-1 if still zero ('KLC').
add a,0x43 ; add 'C' - will become 'E' if originally 1
; or 'G' if originally 2.
jr OUT_C_2 ; forward to OUT-C-2 to print.
; ---
; If mode was zero then, while printing a BASIC line, bit 2 of flags has been
; set if 'THEN' or ':' was encountered as a main character and reset otherwise.
; This is now used to determine if the 'K' cursor is to be printed but this
; transient state is also now transferred permanently to bit 3 of FLAGS
; to let the interrupt routine know how to decode the next key.
;; OUT-C-1
OUT_C_1:
ld hl,0x5C3B ; Address FLAGS
res 3,(hl) ; signal 'K' mode initially.
ld a,0x4B ; prepare letter 'K'.
bit 2,(hl) ; test FLAGS - was the
; previous main character ':' or 'THEN' ?
jr z,OUT_C_2 ; forward to OUT-C-2 if so to print.
set 3,(hl) ; signal 'L' mode to interrupt routine.
; Note. transient bit has been made permanent.
inc a ; augment from 'K' to 'L'.
bit 3,(iy+0x30) ; test FLAGS2 - consider caps lock ?
; which is maintained by KEY-INPUT.
jr z,OUT_C_2 ; forward to OUT-C-2 if not set to print.
ld a,0x43 ; alter 'L' to 'C'.
;; OUT-C-2
OUT_C_2:
push de ; save address pointer but OK as OUT-FLASH
; uses alternate set without RST 10.
call OUT_FLASH ; routine OUT-FLASH to print.
pop de ; restore and
ret ; return.
; ----------------------------
; Get line number of next line
; ----------------------------
; These two subroutines are called while editing.
; This entry point is from ED-DOWN with HL addressing E_PPC
; to fetch the next line number.
; Also from AUTO-LIST with HL addressing S_TOP just to update S_TOP
; with the value of the next line number. It gets fetched but is discarded.
; These routines never get called while the editor is being used for input.
;; LN-FETCH
LN_FETCH:
ld e,(hl) ; fetch low byte
inc hl ; address next
ld d,(hl) ; fetch high byte.
push hl ; save system variable hi pointer.
ex de,hl ; line number to HL,
inc hl ; increment as a starting point.
call LINE_ADDR ; routine LINE-ADDR gets address in HL.
call LINE_NO ; routine LINE-NO gets line number in DE.
pop hl ; restore system variable hi pointer.
; This entry point is from the ED-UP with HL addressing E_PPC_hi
;; LN-STORE
LN_STORE:
bit 5,(iy+0x37) ; test FLAGX - input mode ?
ret nz ; return if so.
t/data/zx48_base.asm view on Meta::CPAN
dec a ; and decrement the digit.
jr z,OUT_SP_2 ; back to OUT-SP-2 if it is zero.
jp OUT_CODE ; jump back to exit via OUT-CODE. ->
; -------------------------------------
; Outputting characters in a BASIC line
; -------------------------------------
; This subroutine ...
;; OUT-CHAR
OUT_CHAR:
call NUMERIC ; routine NUMERIC tests if it is a digit ?
jr nc,OUT_CH_3 ; to OUT-CH-3 to print digit without
; changing mode. Will be 'K' mode if digits
; are at beginning of edit line.
cp 0x21 ; less than quote character ?
jr c,OUT_CH_3 ; to OUT-CH-3 to output controls and space.
res 2,(iy+0x01) ; initialize FLAGS to 'K' mode and leave
; unchanged if this character would precede
; a keyword.
cp 0xCB ; is character 'THEN' token ?
jr z,OUT_CH_3 ; to OUT-CH-3 to output if so.
cp 0x3A ; is it ':' ?
jr nz,OUT_CH_1 ; to OUT-CH-1 if not statement separator
; to change mode back to 'L'.
bit 5,(iy+0x37) ; FLAGX - Input Mode ??
jr nz,OUT_CH_2 ; to OUT-CH-2 if in input as no statements.
; Note. this check should seemingly be at
; the start. Commands seem inappropriate in
; INPUT mode and are rejected by the syntax
; checker anyway.
; unless INPUT LINE is being used.
bit 2,(iy+0x30) ; test FLAGS2 - is the ':' within quotes ?
jr z,OUT_CH_3 ; to OUT-CH-3 if ':' is outside quoted text.
jr OUT_CH_2 ; to OUT-CH-2 as ':' is within quotes
; ---
;; OUT-CH-1
OUT_CH_1:
cp 0x22 ; is it quote character '"' ?
jr nz,OUT_CH_2 ; to OUT-CH-2 with others to set 'L' mode.
push af ; save character.
ld a,(0x5C6A) ; fetch FLAGS2.
xor 0x04 ; toggle the quotes flag.
ld (0x5C6A),a ; update FLAGS2
pop af ; and restore character.
;; OUT-CH-2
OUT_CH_2:
set 2,(iy+0x01) ; update FLAGS - signal L mode if the cursor
; is next.
;; OUT-CH-3
OUT_CH_3:
rst 0x10 ; PRINT-A vectors the character to
; channel 'S', 'K', 'R' or 'P'.
ret ; return.
; -------------------------------------------
; Get starting address of line, or line after
; -------------------------------------------
; This routine is used often to get the address, in HL, of a BASIC line
; number supplied in HL, or failing that the address of the following line
; and the address of the previous line in DE.
;; LINE-ADDR
LINE_ADDR:
push hl ; save line number in HL register
ld hl,(0x5C53) ; fetch start of program from PROG
ld d,h ; transfer address to
ld e,l ; the DE register pair.
;; LINE-AD-1
LINE_AD_1:
pop bc ; restore the line number to BC
call CP_LINES ; routine CP-LINES compares with that
; addressed by HL
ret nc ; return if line has been passed or matched.
; if NZ, address of previous is in DE
push bc ; save the current line number
call NEXT_ONE ; routine NEXT-ONE finds address of next
; line number in DE, previous in HL.
ex de,hl ; switch so next in HL
jr LINE_AD_1 ; back to LINE-AD-1 for another comparison
; --------------------
; Compare line numbers
; --------------------
; This routine compares a line number supplied in BC with an addressed
; line number pointed to by HL.
;; CP-LINES
CP_LINES:
ld a,(hl) ; Load the high byte of line number and
cp b ; compare with that of supplied line number.
ret nz ; return if yet to match (carry will be set).
inc hl ; address low byte of
ld a,(hl) ; number and pick up in A.
dec hl ; step back to first position.
cp c ; now compare.
ret ; zero set if exact match.
; carry set if yet to match.
; no carry indicates a match or
; next available BASIC line or
; program end marker.
; -------------------
; Find each statement
t/data/zx48_base.asm view on Meta::CPAN
; ---
; the jump was here for other variables.
;; IN-ITEM-3
IN_ITEM_3:
call ALPHA ; routine ALPHA checks if character is
; a suitable variable name.
jp nc,IN_NEXT_1 ; forward to IN-NEXT-1 if not
call CLASS_01 ; routine CLASS-01 returns destination
; address of variable to be assigned.
res 7,(iy+0x37) ; update FLAGX - signal not INPUT LINE.
;; IN-PROMPT
IN_PROMPT:
call SYNTAX_Z ; routine SYNTAX-Z
jp z,IN_NEXT_2 ; forward to IN-NEXT-2 if checking syntax.
call SET_WORK ; routine SET-WORK clears workspace.
ld hl,0x5C71 ; point to system variable FLAGX
res 6,(hl) ; signal string result.
set 5,(hl) ; signal in Input Mode for editor.
ld bc,0x0001 ; initialize space required to one for
; the carriage return.
bit 7,(hl) ; test FLAGX - INPUT LINE in use ?
jr nz,IN_PR_2 ; forward to IN-PR-2 if so as that is
; all the space that is required.
ld a,(0x5C3B) ; load accumulator from FLAGS
and 0x40 ; mask to test BIT 6 of FLAGS and clear
; the other bits in A.
; numeric result expected ?
jr nz,IN_PR_1 ; forward to IN-PR-1 if so
ld c,0x03 ; increase space to three bytes for the
; pair of surrounding quotes.
;; IN-PR-1
IN_PR_1:
or (hl) ; if numeric result, set bit 6 of FLAGX.
ld (hl),a ; and update system variable
;; IN-PR-2
IN_PR_2:
rst 0x30 ; BC-SPACES opens 1 or 3 bytes in workspace
ld (hl),0x0D ; insert carriage return at last new location.
ld a,c ; fetch the length, one or three.
rrca ; lose bit 0.
rrca ; test if quotes required.
jr nc,IN_PR_3 ; forward to IN-PR-3 if not.
ld a,0x22 ; load the '"' character
ld (de),a ; place quote in first new location at DE.
dec hl ; decrease HL - from carriage return.
ld (hl),a ; and place a quote in second location.
;; IN-PR-3
IN_PR_3:
ld (0x5C5B),hl ; set keyboard cursor K_CUR to HL
bit 7,(iy+0x37) ; test FLAGX - is this INPUT LINE ??
jr nz,IN_VAR_3 ; forward to IN-VAR-3 if so as input will
; be accepted without checking its syntax.
ld hl,(0x5C5D) ; fetch CH_ADD
push hl ; and save on stack.
ld hl,(0x5C3D) ; fetch ERR_SP
push hl ; and save on stack
;; IN-VAR-1
IN_VAR_1:
ld hl,IN_VAR_1 ; address: IN-VAR-1 - this address
push hl ; is saved on stack to handle errors.
bit 4,(iy+0x30) ; test FLAGS2 - is K channel in use ?
jr z,IN_VAR_2 ; forward to IN-VAR-2 if not using the
; keyboard for input. (??)
ld (0x5C3D),sp ; set ERR_SP to point to IN-VAR-1 on stack.
;; IN-VAR-2
IN_VAR_2:
ld hl,(0x5C61) ; set HL to WORKSP - start of workspace.
call REMOVE_FP ; routine REMOVE-FP removes floating point
; forms when looping in error condition.
ld (iy+0x00),0xFF ; set ERR_NR to 'OK' cancelling the error.
; but X_PTR causes flashing error marker
; to be displayed at each call to the editor.
call EDITOR ; routine EDITOR allows input to be entered
; or corrected if this is second time around.
; if we pass to next then there are no system errors
res 7,(iy+0x01) ; update FLAGS - signal checking syntax
call IN_ASSIGN ; routine IN-ASSIGN checks syntax using
; the VAL-FET-2 and powerful SCANNING routines.
; any syntax error and its back to IN-VAR-1.
; but with the flashing error marker showing
; where the error is.
; Note. the syntax of string input has to be
; checked as the user may have removed the
; bounding quotes or escaped them as with
; "hat" + "stand" for example.
; proceed if syntax passed.
jr IN_VAR_4 ; jump forward to IN-VAR-4
; ---
; the jump was to here when using INPUT LINE.
;; IN-VAR-3
IN_VAR_3:
call EDITOR ; routine EDITOR is called for input
; when ENTER received rejoin other route but with no syntax check.
; INPUT and INPUT LINE converge here.
;; IN-VAR-4
IN_VAR_4:
ld (iy+0x22),0x00 ; set K_CUR_hi to a low value so that the cursor
; no longer appears in the input line.
call IN_CHAN_K ; routine IN-CHAN-K tests if the keyboard
; is being used for input.
jr nz,IN_VAR_5 ; forward to IN-VAR-5 if using another input
; channel.
; continue here if using the keyboard.
call ED_COPY ; routine ED-COPY overprints the edit line
; to the lower screen. The only visible
; affect is that the cursor disappears.
; if you're inputting more than one item in
; a statement then that becomes apparent.
ld bc,(0x5C82) ; fetch line and column from ECHO_E
call CL_SET ; routine CL-SET sets S-POSNL to those
; values.
; if using another input channel rejoin here.
;; IN-VAR-5
IN_VAR_5:
ld hl,0x5C71 ; point HL to FLAGX
res 5,(hl) ; signal not in input mode
bit 7,(hl) ; is this INPUT LINE ?
res 7,(hl) ; cancel the bit anyway.
jr nz,IN_VAR_6 ; forward to IN-VAR-6 if INPUT LINE.
pop hl ; drop the looping address
pop hl ; drop the address of previous
; error handler.
ld (0x5C3D),hl ; set ERR_SP to point to it.
pop hl ; drop original CH_ADD which points to
; INPUT command in BASIC line.
ld (0x5C5F),hl ; save in X_PTR while input is assigned.
set 7,(iy+0x01) ; update FLAGS - Signal running program
call IN_ASSIGN ; routine IN-ASSIGN is called again
; this time the variable will be assigned
; the input value without error.
; Note. the previous example now
; becomes "hatstand"
ld hl,(0x5C5F) ; fetch stored CH_ADD value from X_PTR.
ld (iy+0x26),0x00 ; set X_PTR_hi so that iy is no longer relevant.
ld (0x5C5D),hl ; put restored value back in CH_ADD
jr IN_NEXT_2 ; forward to IN-NEXT-2 to see if anything
; more in the INPUT list.
; ---
; the jump was to here with INPUT LINE only
;; IN-VAR-6
IN_VAR_6:
ld hl,(0x5C63) ; STKBOT points to the end of the input.
ld de,(0x5C61) ; WORKSP points to the beginning.
scf ; prepare for true subtraction.
sbc hl,de ; subtract to get length
ld b,h ; transfer it to
ld c,l ; the BC register pair.
call STK_STO__ ; routine STK-STO-$ stores parameters on
; the calculator stack.
call LET ; routine LET assigns it to destination.
jr IN_NEXT_2 ; forward to IN-NEXT-2 as print items
; not allowed with INPUT LINE.
; Note. that "hat" + "stand" will, for
; example, be unchanged as also would
; 'PRINT "Iris was here"'.
; ---
( run in 0.427 second using v1.01-cache-2.11-cpan-39bf76dae61 )