; 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 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