home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
ZSYS
/
SIMTEL20
/
ZCPR3
/
DEBUGRCP.ASM
< prev
next >
Wrap
Assembly Source File
|
2000-06-30
|
28KB
|
1,587 lines
; SYSTEM SEGMENT: DEBUG.RCP
; SYSTEM: ARIES-1
; CUSTOMIZED BY: RICHARD CONN
;
; PROGRAM: DEBUGRCP.ASM
; AUTHOR: RICHARD CONN
; VERSION: 1.0
; DATE: 30 JUNE 84
; PREVIOUS VERSIONS: NONE
;
VERS EQU 10
RCPID EQU 'A'
;
; DEBUGRCP is a resident debug command package for ZCPR3. As with
; all resident command processors, DEBUGRCP performs the following functions:
;
; 1. Assuming that the EXTFCB contains the name of the
; command, DEBUGRCP looks to see if the first character
; of the file name field in the EXTFCB is a question
; mark; if so, it returns with the Zero Flag Set and
; HL pointing to the internal routine which prints
; its list of commands
; 2. The resident command list in DEBUGRCP is scanned for
; the entry contained in the file name field of
; EXTFCB; if found, DEBUGRCP returns with the Zero Flag
; Set and HL pointing to the internal routine which
; implements the function; if not found, DEBUGRCP returns
; with the Zero Flag Reset (NZ)
;
;
; Global Library which Defines Addresses for DEBUGRCP
;
MACLIB Z3BASE
;
CTRLC EQU 'C'-'@'
BS EQU 08H
TAB EQU 09H
LF EQU 0AH
FF EQU 0CH
CR EQU 0DH
CTRLX EQU 'X'-'@'
;
WBOOT EQU BASE+0000H ;CP/M WARM BOOT ADDRESS
UDFLAG EQU BASE+0004H ;USER NUM IN HIGH NYBBLE, DISK IN LOW
BDOS EQU BASE+0005H ;BDOS FUNCTION CALL ENTRY PT
TFCB EQU BASE+005CH ;DEFAULT FCB BUFFER
FCB1 EQU TFCB ;1st and 2nd FCBs
FCB2 EQU TFCB+16
TBUFF EQU BASE+0080H ;DEFAULT DISK I/O BUFFER
TPA EQU BASE+0100H ;BASE OF TPA
;
; SYSTEM Entry Point
;
org rcp ; passed for Z3BASE
db 'Z3RCP' ; Flag for Package Loader
;
; **** Command Table for RCP ****
; This table is RCP-dependent!
;
; The command name table is structured as follows:
;
; ctable:
; DB 'CMNDNAME' ; Table Record Structure is
; DW cmndaddress ; 8 Chars for Name and 2 Bytes for Adr
; ...
; DB 0 ; End of Table
;
cnsize equ 4 ; NUMBER OF CHARS IN COMMAND NAME
db cnsize ; size of text entries
ctab:
db 'H ' ; Help for RCP
dw clist
ctab1:
db 'MU ' ; Memory Utility
dw mu
;
db 0
;
; BANNER NAME OF RCP
;
rcp$name:
db 'DEBUG '
db (vers/10)+'0','.',(vers mod 10)+'0'
db RCPID
db 0
;
; Command List Routine
;
clist:
lxi h,rcp$name ; print RCP Name
call print1
lxi h,ctab1 ; print table entries
mvi c,1 ; set count for new line
clist1:
mov a,m ; done?
ora a
rz
dcr c ; count down
jnz clist1a
call crlf ; new line
mvi c,4 ; set count
clist1a:
lxi d,entryname ; copy command name into message buffer
mvi b,cnsize ; number of chars
clist2:
mov a,m ; copy
stax d
inx h ; pt to next
inx d
dcr b
jnz clist2
inx h ; skip to next entry
inx h
push h ; save ptr
lxi h,entrymsg ; print message
call print1
pop h ; get ptr
jmp clist1
;
; Print String (terminated in 0 or MSB Set) at Return Address
;
vprint:
eprint:
xthl ; get address
call print1
xthl ; put address
ret
;
; Print String (terminated in 0 or MSB Set) pted to by HL
;
print1:
mov a,m ; done?
inx h ; pt to next
ora a ; 0 terminator
rz
cpi dim ; standout?
jz print1d
cpi bright ; standend?
jz print1b
call cout ; print char
ora a ; set MSB
rm ; MSB terminator
jmp print1
print1d:
call stndout ; dim
jmp print1
print1b:
call stndend ; bright
jmp print1
;
; New Line
;
crlf:
mvi a,cr
call cout
mvi a,lf ;fall thru
;
; Character Output
;
cout:
push psw
push b
push d
push h
mov e,a
mvi c,2 ; use BDOS
call bdos
pop h
pop d
pop b
pop psw
ret
;
; Get char in A
;
cin:
push h
push d
push b
mvi c,1
call bdos
ani 7fh
push psw
mvi a,bs ;overwrite
call cout
pop psw
pop b
pop d
pop h
ret
;
; CLIST Messages
;
entrymsg:
db ' ' ; command name prefix
entryname:
ds cnsize ; command name
db 0 ; terminator
;
; General Equates
;
bel equ 07h
bs equ 08h
cr equ 0dh
lf equ 0ah
fcb equ 5ch
DIM EQU 1
BRIGHT EQU 2
EOLCH EQU 0 ;END OF LINE CHAR
SEPCH EQU ',' ;SEPARATOR CHAR
EROW EQU 6 ;FIRST ROW OF EDITOR DISPLAY
ECOL EQU 4 ;FIRST COL OF EDITOR DISPLAY
ECOLC EQU ECOL+16*3+8 ;FIRST COL OF EDITOR CHAR DISPLAY
ECURS EQU '>' ;EDITOR CURSOR
PRROW EQU 22 ;PROMPT ROW
PRCOL EQU 10 ;PROMPT COLUMN
PRCOLI EQU PRCOL+15 ;PROMPT INPUT COL
ERROW EQU 23 ;ERROR MESSAGE ROW
ERCOL EQU 15 ;ERROR MESSAGE COLUMN
;
; DEFINE FREE SPACE
;
MU:
LXI H,TBUFF ;DETERMINE ADDRESS
MVI M,126 ;126 CHARS INPUT ALLOWED
SHLD BUFFER ;SET PTR
;
; SET UP ARROW KEYS
;
LXI H,Z3ENV ;PT TO ENVIRONMENT DESCRIPTOR
LXI D,80H+10H ;PT TO ARROW KEY INFO
DAD D
LXI D,EDCURT ;PT TO CURSOR TABLE
MVI B,4 ;4 ARROW KEYS
ARROW:
MOV A,M ;GET CHAR
STAX D ;STORE CHAR
INX H ;PT TO NEXT
INX D ;PT TO NEXT ENTRY
INX D
INX D
DCR B ;COUNT DOWN
JNZ ARROW
;
; Initialize Terminal
;
call tinit
;
; Check for Command Line Parameter
;
lxi h,fcb+1 ;pt to first char
mov a,m ;get char
cpi ' ' ;no param?
jnz pcheck
lxi h,tpa ;pt to TPA
jmp mu3
;
; We have a parameter
;
pcheck:
call hexin ;convert to binary
xchg ;HL=value
jmp mu3
;
; Erase to EOL
; If fct not supported, send out B spaces and B backspaces
;
vereol:
call ereol ;try erase
rnz
push b ;save B
mvi a,' ' ;send spaces
call vereol1
pop b ;get B
mvi a,bs ;send backspaces
vereol1:
call cout ;send char in A
dcr b
jnz vereol1
ret
;
; Clear Screen
; If fct not supported, write 24 CRLFs
;
vcls:
call cls ;try clear
rnz
push b ;save B
mvi b,24 ;count
vcls1:
call crlf
dcr b
jnz vcls1
pop b
ret
;
; Run MU3
; HL contains starting address
;
mu3:
SHLD BLOCK ;SAVE PTR TO BLOCK
;
; REFRESH EDIT SCREEN
;
EDIT0:
CALL VCLS ;NEW SCREEN
CALL AT
DB 2,35 ;ROW 2, COL 35
CALL VPRINT ;BANNER
DB 'MU RCP '
DB (VERS/10)+'0','.',(VERS MOD 10)+'0',RCPID
DB 0
;
; REENTER MU3 WITH PTRS RESET
;
MU3R:
XRA A ;A=0
STA EINDEX ;SET INDEX TO 0 (FIRST ELEMENT)
CALL EDPLOT ;PLOT BUFFER DATA
;
; INPUT EDITOR COMMAND
;
EDITCMD:
CALL PRMSG ;POSITION AT PROMPT MESSAGE
DB 'MU Command?',0
CALL PRINP ;POSITION AT PROMPT INPUT
DB 0
CALL CIN ;GET CHAR
CALL CAPS ;CAPITALIZE
MOV B,A ;COMMAND IN B
LXI H,EDCURT ;PROCESS CURSOR COMMANDS FIRST
CALL CMD ;PROCESS COMMAND
LXI H,ECMDTBL ;EDITOR COMMAND TABLE
CALL CMD ;PROCESS COMMAND
CALL VPRINT ;ERROR MESSAGE
DB BEL,0
JMP EDITCMD
;
; Position at Prompt Message and Print it
;
PRMSG:
CALL AT ;POSITION
DB PRROW,PRCOL
JMP VPRINT ;PRINT IT
;
; Position at Prompt Input and Print Prompt
;
PRINP:
CALL AT ;POSITION
DB PRROW,PRCOLI
JMP VPRINT ;PRINT IT
;
;INPUT ERROR
;
WHAT:
CALL VPRINT
DB BEL,0
JMP EDITCMD
;
;Command Table Search and Execute
;
CMD:
MOV A,M ;CHECK FOR END OF TABLE
ORA A
RZ ;COMMAND NOT FOUND
CMP B ;MATCH?
JZ CMDRUN
INX H ;SKIP TO NEXT ENTRY IN TABLE
INX H
INX H
JMP CMD
;
;RUN COMMAND
;
CMDRUN:
INX H ;PT TO LOW ADDRESS
MOV E,M
INX H ;PT TO HIGH ADDRESS
MOV D,M
XCHG
POP PSW ;CLEAR STACK
PCHL ;RUN ROUTINE
;
;PLOT BUFFER DATA
;
EDPLOT:
MVI H,EROW-1 ;SET ROW
MVI L,ECOL ;SET COLUMN
CALL GOTOXY ;POSITION CURSOR
CALL VPRINT
DB DIM
DB ' 0 1 2 3 4 5 6 7 8 9 A B C D E F'
DB BRIGHT,0
INR H ;NEXT ROW
CALL GOTOXY ;POSITION CURSOR
XCHG ;POSITION IN DE
LHLD BLOCK ;PT TO DATA
MVI B,8 ;8 LINES
;
;Print Next Line on Screen
;
EDIT00:
CALL STNDOUT ;GO DIM
MOV A,H ;OUTPUT ADDRESS
CALL PA2HC
MOV A,L
CALL PA2HC
CALL VPRINT
DB ':',BRIGHT,' ',0
MVI C,16 ;16 ELEMENTS
EDIT01:
MOV A,M ;GET BYTE
CALL PA2HC ;PRINT AS HEX
CALL SPACE ;PRINT 1 SPACE
INX H ;PT TO NEXT
DCR C ;COUNT DOWN
JNZ EDIT01
XCHG ;POSITION AGAIN
INR H ;NEXT ROW
CALL GOTOXY
XCHG
DCR B ;COUNT DOWN
JNZ EDIT00
MVI H,EROW ;RESET ROW
MVI L,ECOLC ;RESET COL
CALL GOTOXY ;POSITION CURSOR
XCHG ;POSITION IN DE
LHLD BLOCK ;PT TO DATA
MVI B,8 ;8 LINES
EDIT02:
CALL BAR ;PRINT BAR
MVI C,16 ;16 ELEMENTS
EDIT03:
MOV A,M ;GET BYTE
ANI 7FH ;MASK MSB
CPI 7FH ;DON'T PRINT 7FH
JZ EDIT7F
CPI ' ' ;SPACE OR MORE?
JNC EDIT04
EDIT7F:
MVI A,'.' ;PRINT DOT
EDIT04:
CALL COUT ;PRINT BYTE
INX H ;PT TO NEXT
DCR C ;COUNT DOWN
JNZ EDIT03
CALL BAR ;PRINT ENDING BAR
XCHG ;POSITION AGAIN
INR H ;NEXT ROW
CALL GOTOXY
XCHG
DCR B ;COUNT DOWN
JNZ EDIT02
CALL EDCUR ;POSITION CURSOR
RET
;
;EDITOR COMMAND TABLE
;
ECMDTBL:
DB CR ;NOP
DW EDITCMD
DB 'C'-'@' ;^C = EXIT MU3
DW EDCC
DB 'R'-'@' ;^R = REFRESH
DW EDIT0
DB 'E'-'@' ;^E=UP
DW EDUP
DB 'X'-'@' ;^X=DOWN
DW EDDOWN
DB 'D'-'@' ;^D=RIGHT
DW EDRIGHT
DB 'S'-'@' ;^S=LEFT
DW EDLEFT
DB ' ' ;NOP
DW EDITCMD
DB '+' ;ADVANCE
DW EDITPLUS
DB '-' ;BACKUP
DW EDITMINUS
DB 'A' ;ADDRESS
DW EDITADR
DB 'C' ;COMMAND LINE
DW EDITCL
DB 'N' ;CHANGE NUMBERS
DW EDITHEX
DB 'T' ;CHANGE TEXT
DW EDITALP
DB 0 ;END OF TABLE
;
; ARROW KEY DEFINITONS FROM TCAP
;
EDCURT:
DB 0 ;0 INDICATES NO ARROW KEYS
DW EDUP
DB 0
DW EDDOWN
DB 0
DW EDRIGHT
DB 0
DW EDLEFT
DB 0 ;END OF TABLE
;
;Enter Command Line
;
EDITCL:
CALL VPRINT ;PROMPT INPUT
DB CR,LF,'Command Line? ',0
CALL RDBUF ;INPUT TEXT
CALL PUTCL ;STORE COMMAND LINE
JMP CRLF ;NEW LINE
;
; STORE COMMAND LINE
;
PUTCL:
XCHG ;PTR TO NEW LINE IN DE
CALL GETCL1 ;GET COMMAND LINE DATA
MOV B,A ;CHAR COUNT IN B
XCHG ;HL PTS TO NEW LINE
PUSH H ;SAVE PTR TO NEXT LINE
PCL1:
MOV A,M ;GO TO END OF LINE
ORA A ;AT END?
JZ PCL2
INX H ;PT TO NEXT
DCR B ;COUNT DOWN
JNZ PCL1
POP H ;CLEAR STACK
RET ;COMMAND LINE TOO LONG - ABORT
;
; AT END OF NEW COMMAND LINE
; PTR TO FIRST CHAR OF NEW COMMAND LINE ON STACK
; HL PTS TO ENDING 0 OF NEW COMMAND LINE
; B = NUMBER OF CHARS REMAINING BEFORE COMMAND LINE OVERFLOW
;
PCL2:
XCHG ;DE PTS TO LAST BYTE
PUSH D ;SAVE PTR IN CASE OF ERROR
CALL GETCL2 ;PT TO TAIL OF COMMAND LINE BUFFER
MOV A,M ;GET FIRST CHAR OF TAIL
CPI ';' ;CONTINUATION?
JZ PCL3
ORA A ;DONE?
JZ PCL3
MVI A,';' ;SET CONTINUATION CHAR
STAX D
INX D
DCR B ;COUNT DOWN
JZ PCL4 ;OVERFLOW
;
; COPY TAIL ONTO END OF NEW COMMAND LINE
;
PCL3:
MOV A,M ;GET NEXT CHAR
STAX D ;STORE IT
INX H ;PT TO NEXT
INX D
ORA A ;DONE?
JZ PCL5
DCR B ;COUNT DOWN
JNZ PCL3
;
; COMMAND LINE TOO LONG
;
PCL4:
POP H ;GET PTR TO END OF OLD LINE
MVI M,0 ;STORE ENDING 0
POP PSW ;CLEAR STACK
RET
;
; NEW COMMAND LINE OK
;
PCL5:
POP PSW ;CLEAR STACK
CALL GETCL1 ;GET PTR TO BUFFER
LXI D,4 ;PT TO FIRST CHAR IN BUFFER
XCHG
DAD D
XCHG
MOV M,E ;STORE ADDRESS
INX H
MOV M,D
POP H ;HL PTS TO FIRST CHAR OF NEW LINE
;
; COPY COMMAND LINE INTO BUFFER
;
PCL6:
MOV A,M ;COPY
STAX D
INX H
INX D
ORA A ;DONE?
JNZ PCL6
RET
;
; GETCL1
;
GETCL1:
LHLD Z3ENV+18H ;GET ADDRESS OF COMMAND LINE BUFFER
PUSH H ;SAVE IT
INX H ;GET SIZE IN A
INX H
MOV A,M
POP H
RET
;
; GETCL2
;
GETCL2:
LHLD Z3ENV+18H ;GET ADDRESS OF COMMAND LINE BUFFER
MOV A,M ;GET ADDRESS OF NEXT CHAR
INX H
MOV H,M
MOV L,A ;HL PTS TO NEXT CHAR
MOV A,M ;GET IT
RET
;
;Enter ASCII Chars
;
EDITALP:
CALL PRINP ;PROMPT INPUT
DB DIM,'Enter Text',BRIGHT
DB CR,LF,' --> ',0
CALL RDBUF ;INPUT TEXT WITHOUT PROMPT
CALL EDPRCL ;CLEAR PROMPT LINE
LDA EINDEX ;PT TO POSITION
XCHG
LHLD BLOCK ;COMPUTE OFFSET
XCHG
ADD E
MOV E,A
MOV A,D
ACI 0
MOV D,A ;DE PTS TO BYTE, HL PTS TO TEXT
EDITA1:
MOV A,M ;GET CHAR
CPI EOLCH ;EOL?
JZ EDITA2 ;REFRESH SCREEN
CALL GETAHV ;GET ASCII OR <HEX> VALUE
STAX D ;UPDATE BYTE
INX H ;PT TO NEXT INPUT CHAR
INR E ;PT TO NEXT BUFFER BYTE
JNZ EDITA1
EDITA2:
CALL EDPLOT ;REPLOT
JMP EDITCMD ;DONE-REFRESH SCREEN
;
;Enter Numbers
;
EDITHEX:
CALL PRINP ;PROMPT INPUT
DB DIM,'Enter Hex Numbers'
DB BRIGHT
DB CR,LF,' --> ',0
CALL RDBUF ;INPUT TEXT WITHOUT PROMPT
CALL EDPRCL ;CLEAR PROMPT LINE
LDA EINDEX ;PT TO POSITION
XCHG
LHLD BLOCK ;COMPUTE OFFSET
XCHG
ADD E
MOV E,A
MOV A,D
ACI 0
MOV D,A ;DE PTS TO BYTE, HL PTS TO TEXT
EDITH1:
MOV A,M ;GET HEX DIGIT
CPI EOLCH ;EOL?
JZ EDITA2 ;REFRESH SCREEN
CPI ' ' ;SKIP SPACES
JNZ EDITH2
INX H ;SKIP SPACE
JMP EDITH1
EDITH2:
PUSH D ;SAVE PTR
CALL HEXIN ;GET VALUE AND POSITION HL
MOV A,E ;... IN A
POP D ;GET PTR
STAX D ;PUT BYTE
INR E ;ADVANCE TO NEXT BYTE
JNZ EDITH1
JMP EDITA2 ;DONE-REFRESH
;
;CLEAR PROMPT LINE
;
EDPRCL:
CALL PRINP ;PROMPT LINE
DB 0
MVI B,40 ;40 POSITIONS
CALL VEREOL ;CLEAR TO EOL OR 40 CHARS
CALL AT ;USER INPUT
DB ERROW,1
MVI B,79 ;79 POSITIONS
JMP VEREOL
;
;Input Address
;
EDITADR:
CALL VPRINT
DB 'Address? ',0
CALL RDBUF ;GET USER INPUT
CALL SKSP ;SKIP LEADING SPACES
MOV A,M ;EMPTY LINE?
ORA A
JZ EDIT0
CALL HEXIN ;CONVERT FROM HEX
XCHG ;HL = ADDRESS
SHLD BLOCK
JMP EDIT0 ;REENTER
;
;Advance to Next Block
;
EDITPLUS:
LHLD BLOCK ;ADVANCE TO NEXT BLOCK
LXI D,128 ;128 BYTES
DAD D
SHLD BLOCK
JMP MU3R
;
;Backup to Last Block
;
EDITMINUS:
LHLD BLOCK ;BACKUP TO LAST BLOCK
LXI D,-128 ;128 BYTES
DAD D
SHLD BLOCK
JMP MU3R
;
;Exit MU3
;
EDCC:
CALL DINIT ;DEINIT TERM
JMP CRLF ;NEW LINE
;
;EDIT MOVE: UP
;
EDUP:
CALL EDCCUR ;CLEAR CURSOR
LDA EINDEX ;BACKUP INDEX BY 16
SUI 16
;
;Common EDIT MOVE Routine - on input, A=new index
;
EDMOVE:
ANI 7FH ;MOD 128
STA EINDEX
CALL EDCUR ;SET CURSOR
JMP EDITCMD
;
;EDIT MOVE: DOWN
;
EDDOWN:
CALL EDCCUR ;CLEAR CURSOR
LDA EINDEX ;INCREMENT INDEX BY 16
ADI 16
JMP EDMOVE ;COMMON ROUTINE
;
;EDIT MOVE: RIGHT
;
EDRIGHT:
CALL EDCCUR ;CLEAR CURSOR
LDA EINDEX ;INCREMENT INDEX BY 1
INR A
JMP EDMOVE ;COMMON ROUTINE
;
;EDIT MOVE: LEFT
;
EDLEFT:
CALL EDCCUR ;CLEAR CURSOR
LDA EINDEX ;DECREMENT INDEX BY 1
DCR A
JMP EDMOVE ;COMMON ROUTINE
;
;EDIT SUBROUTINE: EDCUR
; Position Editor Cursor at EINDEX
;EDIT SUBROUTINE: EDCCUR
; Clear Editor Cursor at EINDEX
;
EDCUR:
PUSH H ;SAVE HL
MVI C,ECURS ;CURSOR CHAR
CALL EDSETCUR
CALL AT ;UPDATE DATA
DB 3,74
LDA EINDEX ;PT TO BYTE AT CURSOR
LHLD BLOCK
ADD L
MOV L,A
MOV A,H
ACI 0
MOV H,A ;HL PTS TO BYTE AT CURSOR
MOV A,M ;GET BYTE
CALL PA2HC ;PRINT AS HEX
CALL SPACE
MOV A,M ;GET BYTE
POP H ;RESTORE HL
ANI 7FH ;MASK
CPI 7FH ;7FH AS DOT
JZ EDC7F
CPI ' ' ;OUTPUT CHAR OR DOT
JNC COUT
EDC7F:
MVI A,'.' ;DOT
JMP COUT
EDCCUR:
MVI C,' ' ;CLEAR CURSOR
EDSETCUR:
CALL EDROW ;COMPUTE ROW
ANI 0FH ;COMPUTE COL MOD 16
MOV B,A ;RESULT IN B
ADD A ;*2
ADD B ;*3
ADI ECOL+6 ;ADD IN COL
DCR A ;SUBTRACT 1
MOV L,A ;COL POSITION SET
CALL GOTOXY ;POSITION CURSOR
MOV A,C ;OUTPUT CHAR
JMP COUT
;
;Compute Row from EINDEX
;
EDROW:
LDA EINDEX ;GET INDEX
MOV B,A ;SAVE IN B
RRC ;DIVIDE BY 16
RRC
RRC
RRC
ANI 0FH ;MASK FOR LSB ONLY
ADI EROW ;COMPUTE ROW
MOV H,A ;ROW SET
MOV A,B ;GET INDEX
RET
;
;PRINT A SPACE
;
SPACE:
MVI A,' '
JMP COUT
;
;PRINT AN BARISK IN REV VIDEO
;
BAR:
CALL VPRINT
DB DIM,'|',BRIGHT,0
RET
;
;Get value from input buffer
;
GETAHV:
MOV A,M ;GET NEXT CHAR
CPI '<' ;HEX ESCAPE?
RNZ ;NO, RETURN
;"<<" means one "<"
INX H
MOV A,M
CPI '<'
RZ
;Got hex
PUSH D
CALL HEXIN ;GET VALUE
CPI '>' ;PROPER DELIM?
MOV A,E ;GET VALUE
POP D
RZ
;
;ERROR CONDITION IN SUBROUTINE - CLEAR STACK AND FLAG ERROR
;
SERR:
POP PSW ;CLEAR STACK
JMP WHAT ;ERROR
;
;Input Number from Command Line -- Assume it to be Hex
; Number returned in DE
;
HEXIN:
LXI D,0 ;INIT VALUE
MOV A,M
CPI '#' ;DECIMAL?
JZ HDIN ;MAKE DECIMAL
;
HINLP:
MOV A,M ;GET CHAR
CALL CAPS ;CAPITALIZE
CPI CR ;EOL?
RZ
CPI EOLCH ;EOL?
RZ
CPI SEPCH
RZ
CPI ' ' ;SPACE?
RZ
CPI '-' ;'THRU'?
RZ
CPI '>'
RZ
INX H ;PT TO NEXT CHAR
CPI '0' ;RANGE?
JC SERR
CPI '9'+1 ;RANGE?
JC HINNUM
CPI 'A' ;RANGE?
JC SERR
CPI 'F'+1 ;RANGE?
JNC SERR
SUI 7 ;ADJUST FROM A-F TO 10-15
;
HINNUM:
SUI '0' ;CONVERT FROM ASCII TO BINARY
XCHG
DAD H ;MULT PREVIOUS VALUE BY 16
DAD H
DAD H
DAD H
ADD L ;ADD IN NEW DIGIT
MOV L,A
XCHG
JMP HINLP
;
HDIN:
INX H ;SKIP '#'
;
;Input Number in Command Line as Decimal
; Number is returned in DE
;
DECIN:
LXI D,0
MOV A,M ; GET 1ST CHAR
CPI '#' ; HEX?
JNZ DINLP
INX H ; PT TO DIGIT
JMP HINLP ; DO HEX PROCESSING
;
DINLP:
MOV A,M ;GET DIGIT
CALL CAPS ;CAPITALIZE
CPI '0' ;RANGE?
RC
CPI '9'+1 ;RANGE?
RNC
SUI '0' ;CONVERT TO BINARY
INX H ;PT TO NEXT
PUSH H
MOV H,D
MOV L,E
DAD H ;X2
DAD H ;X4
DAD D ;X5
DAD H ;X10
ADD L ;ADD IN DIGIT
MOV L,A
MOV A,H
ACI 0
MOV H,A
XCHG ;RESULT IN DE
POP H
JMP DINLP
;
; READ LINE FROM USER INTO INPUT LINE BUFFER
;
RDBUF:
LHLD BUFFER ;PT TO BUFFER
XCHG ;SET DE AS PTR TO BUFFER
MVI C,10 ;BDOS READLN
PUSH D ;SAVE PTR
CALL BDOS
POP H ;PT TO CHAR COUNT
INX H
MOV E,M ;GET CHAR COUNT
MVI D,0
INX H ;PT TO FIRST CHAR
PUSH H ;SAVE PTR
DAD D ;PT TO AFTER LAST CHAR
MVI M,0 ;STORE ENDING 0
POP H ;PT TO FIRST CHAR
RET
;
; Capitalize char in A
;
caps:
ani 7fh
cpi 'a' ;range?
rc
cpi 'z'+1
rnc
ani 5fh ;mask to caps
ret
;
; CLEAR SCREEN ON TERMINAL
;
cls:
push h ;save regs
push d
lxi h,z3env+80H ;pt to environment
mov a,m ;no terminal?
cpi ' '+1
jc clserr
lxi d,14h ;pt to cls delay
dad d
mov d,m ;get it
inx h ;pt to cls string
inx h
inx h
mov a,m ;get first char of string
ora a ;if no string, error
jz clserr
call vidout ;output string with delay
pop d ;done
pop h
xra a ;return NZ
dcr a
ret
clserr:
pop d ;done
pop h
xra a ;return Z
ret
;
; Erase to End of Line
; Return with A=0 and Zero Flag Set if not done
;
ereol:
push b ;save regs
push d
push h
lxi h,z3env+80h ;pt to environment
mov a,m ;no terminal?
cpi ' '+1
jc err
lxi d,16h ;pt to ereol delay
dad d
mov d,m ;get it
inx h ;pt to cls string
call vidskp ;skip over it
call vidskp ;skip over CM string
mov a,m ;get first char of ereol string
ora a ;if no string, error
jz err
call vidout ;output string with delay
jmp noerr
;
; GOTO XY
; HL = Row/Col, with Home=1/1
; Return with A=0 and Zero Flag Set if not done
;
gotoxy:
push b ;save regs
push d
push h
lxi h,z3env+80h ;pt to environment
mov a,m ;no terminal?
cpi ' '+1
jc err
lxi d,15h ;pt to CM delay
dad d
mov a,m ;get it
sta cmdelay ;save it
inx h ;pt to CL string
inx h
call vidskp ;skip CL string
mov a,m ;get first char of CM string
ora a ;if no string, error
jz err
xchg ;DE=address of CM string
pop h ;get coordinates in HL
push h
call gxy ;output xy string with delay
lda cmdelay ;pause
call videlay
noerr:
pop h ;done
pop d
pop b
xra a ;return NZ
dcr a
ret
err:
pop h ;done
pop d
pop b
xra a ;return Z
ret
;
; Position Cursor at Location Specified by Return Address
; Usage:
; call at
; db row,col ;location
;
at:
xthl ;pt to address
push d ;save DE
mov d,m ;get row
inx h
mov e,m
inx h ;HL pts to return byte
xchg ;DE pts to return byte, HL contains screen loc
call gotoxy ;position cursor
xchg ;HL pts to return byte
pop d ;restore registers
xthl ;restore stack ptr
ret
;
; GOTOXY
; On input, H=Row and L=Column to Position To (1,1 is Home)
; On input, DE=address of CM string
;
gxy:
dcr h ;adjust to 0,0 for home
dcr l
xra a ;set row/column
sta rcorder ;row before column
sta rcbase ;add 0 to base
;
; Cycle thru string
;
gxyloop:
ldax d ;get next char
inx d ;pt to next
ora a ;done?
rz
cpi '%' ;command?
jz gxycmd
cpi '\' ;escape?
jz gxyesc
call cout ;send char
jmp gxyloop
;
; Escape - output following byte literally
;
gxyesc:
ldax d ;get next char
call cout ;output literally
inx d ;pt to next
jmp gxyloop
;
; Interpret next character as a command character
;
gxycmd:
ldax d ;get command char
inx d ;pt to next
cpi 'd' ;%d
jz gxyout1
cpi '2' ;%2
jz gxyout2
cpi '3' ;%3
jz gxyout3
cpi '.' ;%.
jz gxyout4
cpi '+' ;%+v
jz gxyout5
cpi '>' ;%>xy
jz gxygt
cpi 'r' ;%r
jz gxyrev
cpi 'i' ;%i
jz gxyinc
call cout ;output char if nothing else
jmp gxyloop
;
; Set row/col home to 1,1 rather than 0,0
;
gxyinc:
mvi a,1 ;set rcbase to 1
sta rcbase
jmp gxyloop
;
; Reverse order of output to column then row (default is row then column)
;
gxyrev:
mvi a,1 ;set column and row order
sta rcorder
jmp gxyloop
;
; Command: >xy
; If value of row/col is greater than x, add y to it
;
gxygt:
call getval ;get value
mov c,a ;save value
ldax d ;get value to test
inx d ;pt to next
cmp c ;if carry, value>x
jnc gxygt1
ldax d ;get value to add
add c
call putval ;put value back
gxygt1:
inx d ;pt to next
jmp gxyloop ;resume
;
; Command: +n
; Add n to next value and output
;
gxyout5:
ldax d ;get value to add
inx d ;pt to next
mov b,a ;save in B
call getval ;get value
add b ;add in B
call cout ;output value
rcmark:
lda rcorder ;mark output
ori 80h
sta rcorder
jmp gxyloop
;
; Command: .
; Output next value
;
gxyout4:
call getval ;get value
call cout ;output value
jmp rcmark
;
; Command: 3
; Output next value as 3 decimal digits
;
gxyout3:
call getval ;get value
mvi b,100 ;output 100's
mvi c,1 ;leading zeroes
call digout
gxyot3:
mvi b,10 ;output 10's
mvi c,1 ;leading zeroes
gxyot2:
call digout
adi '0' ;output 1's
call cout
jmp rcmark
;
; Command: 2
; Output next value as 2 decimal digits
;
gxyout2:
call getval ;get value
jmp gxyot3
;
; Command: d
; Output next value as n decimal digits with no leading zeroes
;
gxyout1:
call getval ;get value
mvi b,100 ;output 100's
mvi c,0 ;no leading zeroes
call digout
mvi b,10 ;output 10's
mvi c,0 ;no leading zeroes
jmp gxyot2
;
; Return next value in A
;
getval:
lda rcorder ;get order flag
ora a ;already output the first value?
jm getval2
ani 1 ;look at lsb
jz getvalr ;if 0, row first
getvalc:
lda rcbase ;get base offset
add l ;get column
ret
getvalr:
lda rcbase ;get base offset
add h ;get row
ret
getval2:
ani 1 ;look at lsb
jz getvalc
jmp getvalr
;
; Store A as next value
;
putval:
mov c,a ;save value
lda rcorder ;get order flag
ora a ;already output the first value?
jm putval2
ani 1 ;look at lsb
jz putvalr ;if 0, row first
putvalc:
mov l,c ;set column
ret
putvalr:
mov h,c ;set row
ret
putval2:
ani 1 ;look at lsb
jz putvalc
jmp putvalr
;
; Output A as decimal digit char
; B=Quantity to Subtract from A, C=0 if no leading zero
;
digout:
push d ;save DE
mvi d,'0' ;char
decot1:
sub b ;subtract
jc decot2
inr d ;increment char
jmp decot1
decot2:
add b ;add back in
push psw ;save result
mov a,d ;get digit
cpi '0' ;zero?
jnz decot3
mov a,c ;get zero flag
ora a ;0=no zero
jz decot4
decot3:
mov a,d ;get digit
call cout ;print it
decot4:
pop psw ;get A
pop d ;restore DE
ret
;
; GXY Buffers
;
rcorder:
ds 1 ;0=row/col, else col/row
rcbase:
ds 1 ;0=org is 0,0, else org is 1,1
cmdelay:
ds 1 ;number of milliseconds to delay for CM
;
; Begin Standout Mode
; Return with A=0 and Zero Flag Set if not done
;
stndout:
push b
push d
push h ;save regs
lxi h,z3env+80h ;pt to environment
mov a,m ;no terminal?
cpi ' '+1
jc err
lxi d,17h ;pt to cls string
dad d
mvi d,0 ;no delay
call vidskp ;skip over CL string
call vidskp ;skip over CM string
call vidskp ;skip over CE string
mov a,m ;get first char of SO string
ora a ;if no string, error
jz err
call vidout ;output string with delay
jmp noerr
;
; Terminate Standout Mode
; Return with A=0 and Zero Flag Set if not done
;
stndend:
push b
push d
push h ;save regs
lxi h,z3env+80h ;pt to environment
mov a,m ;no terminal?
cpi ' '+1
jc err
lxi d,17h ;pt to cls string
dad d
mvi d,0 ;no delay
call vidskp ;skip over CL string
call vidskp ;skip over CM string
call vidskp ;skip over CE string
call vidskp ;skip over SO string
mov a,m ;get first char of SE string
ora a ;if no string, error
jz err
call vidout ;output string with delay
jmp noerr
;
; Initialize Terminal
; Affect No Registers
;
tinit:
push h ;save regs
push d
push psw
lxi h,z3env+80h ;pt to environment
mov a,m ;no terminal?
cpi ' '+1
jc tid
lxi d,17h ;pt to cls string
dad d
mvi d,0 ;no delay
call vidskp ;skip over CL string
call vidskp ;skip over CM string
call vidskp ;skip over CE string
call vidskp ;skip over SO string
call vidskp ;skip over SE string
mov a,m ;get first char of TI string
ora a ;if no string, error
jz tid
call vidout ;output string with delay
tid:
pop psw ;done
pop d
pop h
ret
;
; De-Initialize Terminal
; Affect No Registers
;
dinit:
push h ;save regs
push d
push psw
lxi h,z3env+80h ;pt to environment
mov a,m ;no terminal?
cpi ' '+1
jc tid
lxi d,17h ;pt to cls string
dad d
mvi d,0 ;no delay
call vidskp ;skip over CL string
call vidskp ;skip over CM string
call vidskp ;skip over CE string
call vidskp ;skip over SO string
call vidskp ;skip over SE string
call vidskp ;skip over TI string
mov a,m ;get first char of TE string
ora a ;if no string, error
jz tid
call vidout ;output string with delay
jmp tid
;
; VIDOUT - Output video string pted to by HL
; Output also a delay contained in the D register
;
vidout:
mov a,m ;get next char
ora a ;done if zero
jz vid2
inx h ;pt to next
cpi '\' ;literal value?
jnz vid1
mov a,m ;get literal char
inx h ;pt to after it
vid1:
call cout ;output char
jmp vidout
vid2:
mov a,d ;output delay and fall thru to VIDELAY
;
; VIDELAY pauses for the number of milliseconds indicated by the A
; register. VIDELAY assumes a ZCPR3 environment and uses it to determine
; processor speed.
;
videlay:
push psw ;save regs
push b
push d
push h
mov c,a ;save count in C
ora a ;no delay?
jz done
lxi h,z3env ;pt to environment
lxi d,2Bh ;offset to processor speed
dad d
mov a,m ;get processor speed
ora a ;zero?
jnz vidl1
mvi a,4 ;assume 4 MHz
vidl1:
mov b,a ;processor speed in B
vidl2:
push b ;delay 1 ms
call delay
pop b
dcr c ;count down
jnz vidl2
done:
pop h ;restore regs
pop d
pop b
pop psw
ret
;
; Delay 1 ms at Clock speed
;
delay:
call del1 ;delay 1 ms at 1MHz
dcr b ;count down clock speed
jnz delay
ret
;
; Delay 1 ms at 1MHz
;
del1:
mvi c,20 ;20 loops of 51 cycles each ~ 1000 cycles
del1a:
xthl ;18 cycles
xthl ;+18 = 36 cycles
dcr c ;+ 5 = 41 cycles
jnz del1a ;+10 = 51 cycles
ret
;
; VIDSKP - Skip over video string pted to by HL; pt to byte after string
;
vidskp:
mov a,m ;get next char
inx h ;pt to next
ora a ;done if zero
rz
cpi '\' ;literal value?
jnz vidskp ;continue if not
inx h ;pt to after literal value
jmp vidskp
;
; Print A as 2 Hex Chars
;
pa2hc:
push psw
push b
mov b,a ;value in B
rlc
rlc
rlc
rlc
call pa2hc1
mov a,b ;get value
call pa2hc1
pop b
pop psw
ret
pa2hc1:
ani 0fh
adi '0' ;to ASCII
cpi '9'+1
jc pa2hc2
adi 7 ;to letter
pa2hc2:
jmp cout
;
; Skip Spaces
;
sksp:
mov a,m ;skip to non-space
cpi ' '
rnz
inx h
jmp sksp
;
;EDITOR BUFFERS
;
BLOCK:
DS 2 ;ADDRESS OF CURRENT BLOCK
BUFFER:
DS 2 ;PTR TO FREE SPACE
EINDEX:
DS 1 ;INDEX ENTRY
EDRUN:
DS 1 ;FLAG SAYING THAT EDITOR IS RUNNING
end