;MACROS LIBRARY FOR CP/M ROUTINE SIMULATION 10/15/80 ;CONTAINS: ; 1) INBUF - DUPLICATES READ BUFFER ROUTINE ; SAME AS CP/M FUNCTION 10, BUT DOES ; NOT USE CTRL-C (REASON FOR ROUTINE). ; DOES ALLOW CONTROLS U, R, E, AND H (BACKSPACE). ; OUTPUTS BELL IF INPUT GREATER THAN BUFFER ; 2) CMDLINE - PARSES A CP/M BUFFER INTO FORMAT SAME AS ; CP/M COMMAND LINE. ; 3) INLNCOMP - COMPARES STRINGS FOLLOWING CALL TO 'ILCOMP' ; TO STRING ADDRESSED BY DE REGS. ; 4) MULTNAME - MULTI-FILE FILE ACCESS ROUTINE FROM ; CP/M USERS GROUP. ; 5) DIRLIST - LISTS DIRECTORY INBUF MACRO ;NO PARAMETERS USED. LOCAL START,INBUFO,INBUFA,DELETE,NODEL,ALERT LOCAL INBUFLT,CLEAR,CLEARL,INBUFR,RETYPE,BKSPC,PCRLF LOCAL CONIN,CONOUT,CONIN1,CONOUT1,NOUCASE,CTLRLP LOCAL CONSTAT,CONST1,CONINLP PUSH PSW PUSH H PUSH B PUSH D ;DE REGISTERS MUST BE PUSHED LAST START CALL CLEAR ;CLEAR THE BUFFER AREA POP D ;GET ADDRESS OF BUFFER ON RETRIES PUSH D ;RESTORE STACK XRA A INX D ;ADDRESS COUNT FIELD STAX D ;INITIALIZE WITH A ZERO IN COUNT BYTE INX D XCHG ;ADDRESS FIRST BUFFER BYTE WITH HL INBUFA CALL CONIN CPI 0DH ;IS IT A RETURN? JZ INBUFR ;IF SO, THEN RETURN CPI 7FH ;IS IT A DELETE? JZ DELETE CPI 8 ;CTRL-H WILL BACKSPACE.. JZ DELETE ;..OVER DELETED CHAR. CPI 'U'-40H ;IS IT A CTRL-U JZ INBUFO ;OUTPUT # CR LF AND START OVER CPI 'R'-40H ;CTRL-R RETYPES LINE JZ RETYPE CPI 'E'-40H JZ PCRLF CPI 20H ;NO CONTROL CHARACTERS OTHER.. JC INBUFA ;..THAN ABOVE ALLOWED. MOV B,A ;SAVE INPUTTED CHARACTER XCHG ;SAVE HL IN DE POP H ;GET ADDRESS OF BUFFER IN HL PUSH H ;RESTORE STACK INX H ;ADDRESS COUNT BYTE INR M ;INCREASE COUNT BYTE DCX H ;ADDRESS MAXIMUM MOV A,M ;PUT MAXIMUM IN A INX H ;ADDRESS COUNT CMP M ;COMPARE COUNT TO MAXIMUM JC ALERT ;IF MAXIMUM, RING BELL AND WAIT FOR CR XCHG ;RESTORE BUFFER POINTER TO HL MOV M,B ;PUT INPUTTED CHARACTER IN BUFFER MOV A,B ;OUTPUT IT CALL CONOUT INX H ;BUMP POINTER JMP INBUFA ;GET NEXT CHARACTER DELETE XCHG ;SAVE BUFFER POINTER IN DE POP H ;ADDRESS BEGINNING OF BUFFER PUSH H ;RESTORE STACK INX H ;ADDRESS COUNT FIELD MOV B,A ;SAVE DELETE CHAR - 7FH OR 08H MOV A,M SUI 1 ;DECREASE COUNT MOV M,A JC NODEL ;DON'T DELETE PAST BEGINING OF BUFFER. XCHG ;RESTORE BUFFER POINTER TO HL DCX H ;POINT TO LAST BYTE INPUTTED MOV A,B ;GET BACK EITHER 7FH OR 08H MOV B,M ;GET CHARACTER BEING DELETED MVI M,20H ;RESTORE BLANK CPI 8 JZ BKSPC MOV A,B ;ECHO CHAR IF 7FH CALL CONOUT JMP INBUFA ;GET NEXT CHARACTER NODEL INR M ;DON'T LEAVE COUNT NEGATIVE XCHG ;RESTORE POINTER TO HL JMP INBUFA BKSPC CALL CONOUT ;TRUE ERASE IF 08H MVI A,20H CALL CONOUT MVI A,8 CALL CONOUT JMP INBUFA INBUFO MVI A,'#' CALL CONOUT MVI A,0DH CALL CONOUT MVI A,0AH CALL CONOUT JMP START RETYPE POP D PUSH D INX D ;POINT TO CURRENT NUMBER.. LDAX D ;..OF CHARACTERS. MOV B,A MVI A,'#' CALL CONOUT MVI A,0DH CALL CONOUT MVI A,0AH CALL CONOUT MOV A,B ;TEST IF ZERO INPUT ORA A JZ INBUFA CTLRLP INX D LDAX D CALL CONOUT DCR B JNZ CTLRLP JMP INBUFA ALERT MVI A,7 CALL CONOUT DCR M XCHG JMP INBUFA PCRLF MVI A,0DH CALL CONOUT MVI A,0AH CALL CONOUT JMP INBUFA INBUFR MVI A,0DH CALL CONOUT MVI A,0AH CALL CONOUT POP D POP B POP H POP PSW RET CLEAR POP D ;ACCOUNTS FOR CALL POP H ;ADDRESS BUFFER IN HL PUSH H ;RESTORE.. PUSH D ;..STACK MOV B,M ;SAVE MAXIMUM IN B INX H ;POINT TO FIRST.. INX H ;..BUFFER BYTE. MVI A,20H CLEARL MOV M,A INX H DCR B JNZ CLEARL RET CONIN PUSH H ! PUSH D ! PUSH B CONINLP CALL CONSTAT ORA A JZ CONINLP CALL CONIN1 CPI 61H ;CHANGE TO UPPER.. JC NOUCASE ;..CASE SINCE CP/M.. CPI 7BH ;..DOES THE SAME. JNC NOUCASE ANI 5FH NOUCASE POP B ! POP D ! POP H RET CONIN1 LHLD 1 LXI D,6 DAD D PCHL CONSTAT PUSH H ! PUSH D ! PUSH B CALL CONST1 POP B ! POP D ! POP H RET CONST1 LHLD 1 LXI D,3 DAD D PCHL CONOUT PUSH H ! PUSH D ! PUSH B ! PUSH PSW CALL CONOUT1 POP PSW ! POP B ! POP D ! POP H RET CONOUT1 LHLD 1 LXI D,9 DAD D MOV C,A PCHL ENDM CMDLINE MACRO ;NO PARAMETERS USED ;LOADS A COMMAND LINE ADDRESSED BY DE REGISTERS (MAX # CHARACTERS IN LINE ;IN DE, NUMBER OF CHARS IN LINE IN DE+1, LINE STARTS IN DE+2) INTO FCB ;ADDRESSED BY HL REGISTERS. THE FCB SHOULD BE AT LEAST 33 BYTES IN LENGTH. ;THE COMMAND LINE BUFFER MUST HAVE A MAXIMUM LENGTH OF AT LEAST ONE MORE ;THAN THE GREATEST NUMBER OF CHARACTERS THAT WILL BE NEEDED. LOCAL CMDLINE, DEFDR, DONE, DRIVE, FILL1, FILL, FILL2, INIT, INITL1 LOCAL INITL2, INITL3, INITL4, NAME1, NAME2, SCAN, TRANS, TSTNAM LOCAL TSTTYP, TSTTYPL, TYPE1, TYPE2, NAME2C PUSH PSW PUSH B PUSH D PUSH H CALL INIT ;FILLS FCBS WITH BLANKS AND NULLS XCHG ;GET START OF COMMAND LINE IN HL. INX H ;ADDRESS # BYTES IN CMD LINE. MOV E,M ;LOAD DE PAIR WITH # BYTES. MVI D,0 INX H DAD D ;POINT TO BYTE AFTER LAST CHAR.. MVI M,0DH ;..IN CMD LINE AND STORE DELIMITER. POP H ;RESTORE HL AND DE. POP D PUSH D PUSH H INX D ;ADDRESS START OF COMMAND. INX D CALL DRIVE NAME1 MVI C,8 ;TRANSFER FIRST FILENAME TO FCB. CALL TRANS CPI 0DH JZ DONE CPI 20H ;IF SPACE, THEN START OF.. JZ NAME2 ;..SECOND FILENAME. TYPE1 POP H ;FILETYPE MUST BE AFTER.. PUSH H ;..EIGHTH BYTE OF NAME. LXI B,9 DAD B MVI C,3 ;TRANSFER TYPE OF FIRST FILE CALL TRANS CPI 0DH JZ DONE NAME2 LDAX D ;EAT MULTIPLE SPACES.. CPI 20H ;..BETWEEN NAMES. JNZ NAME2C INX D JMP NAME2 LDAX D CPI 0DH ;TEST IF FIRST NAME.. JZ DONE ;..ONLY AND THEN SPACE. NAME2C POP H ;SECOND NAME STARTS IN 16TH BYTE. PUSH H ;POINT HL TO THIS BYTE. LXI B,16 DAD B CALL DRIVE MVI C,8 CALL TRANS CPI 0DH JZ DONE TYPE2 POP H ;SECOND TYPE STARTS IN 25TH BYTE. PUSH H LXI B,25 DAD B MVI C,3 CALL TRANS DONE POP H PUSH H INX H ;POINT TO FIRST CHAR OF FIRST NAME IN FCB. CALL SCAN ;CHECK FOR * (AMBIGUOUS NAMES). POP H PUSH H LXI B,17 ;POINT TO FIRST CHAR OF SECOND NAME IN FCB. DAD B CALL SCAN POP H POP D POP B POP PSW RET ; =============>>> SUBROUTINES <<=============== INIT PUSH H ;INITIALIZES FCB WITH 1 NULL (FOR FIRST DRIVE),.. PUSH B ;..11 BLANKS, 4 NULLS, 1 NULL (FOR 2ND DRIVE),.. MVI M,0 ;..11 BLANKS, AND 4 NULLS. INX H MVI B,11 MVI A,20H CALL INITFILL MVI B,5 MVI A,0 CALL INITFILL MVI B,11 MVI A,20H CALL INITFILL MVI B,4 MVI A,0 CALL INITFILL POP B POP H RET INITFILL MOV M,A INX H DCR B JNZ INITFILL RET DRIVE INX D ;CHECK 2ND BYTE OF FILENAME. IF IT.. LDAX D ;..IS A ":", THEN DRIVE WAS SPECIFIED. DCX D CPI ':' JNZ DEFDR ;ELSE ZERO FOR DEFAULT DRIVE ('INIT' PUT ZERO) LDAX D ANI 5FH SUI 40H ;CALCULATE DRIVE (A=1, B=2,...).. MOV M,A ;..AND PLACE IT IN FCB. INX D ;ADDRESS FIRST BYTE OF.. INX D ;..IN CMD LINE,.. DEFDR INX H ;..AND NAME FIELD IN FCB. RET TRANS LDAX D ;TRANSFER FROM CMD LINE TO FCB.. INX D ;..UP TO NUMBER OF CHARS SPECIFIED.. CPI 0DH ;..BY C-REG. KEEP SCANNING FIELD.. RZ ;..WITHOUT TRANSFER UNTIL A DELIMITING.. CPI '.' ;..FIELD CHAR SUCH AS '.', BLANK, OR.. RZ ;..C/R (FOR END OF CMD LINE). CPI 20H RZ DCR C JM TRANS ;ONCE C-REG IS LESS THAN ZERO, KEEP READING.. MOV M,A ;..CMD LINE BUT DO NOT TRANSFER TO FCB. INX H JMP TRANS SCAN MVI B,8 ;SCAN FILE NAME ADDRESSED BY HL. TSTNAM MOV A,M CPI '*' ;IF '*' FOUND, FILL IN REST OF FIELD.. JZ FILL1 ;..WITH '?' FOR AMBIGUOUS NAME. INX H DCR B JNZ TSTNAM JMP TSTTYP FILL1 CALL FILL TSTTYP MVI B,3 ;SCAN AND FILL TYPE FIELD FOR NAME.. TSTTYPL MOV A,M ;..SPECIFIED ABOVE. CPI '*' JZ FILL2 INX H DCR B RZ JMP TSTTYPL FILL2 CALL FILL RET FILL MVI M,'?' ;ROUTINE TRANSFERS '?'. INX H DCR B JNZ FILL RET ENDM INLNCOMP MACRO ;NO PARAMETERS USED ;IN-LINE COMPARE. COMPARES STRING ADDRESSED BY DE-REG TO STRING ;AFTER CALL (ENDS WITH ZERO). RETURN WITH CARRY SET MEANS STRINGS ;NOT THE SAME. ALL REGISTERS EXCEPT A-REG ARE UNAFFECTED. LOCAL ILCOMPL, SAME, NOTSAME, NSLP XTHL ;POINT HL TO 1ST CHAR. PUSH D ILCOMPL MOV A,M ;HL POINTS TO IN-LINE STRING. ORA A ;END OF STRING IF ZERO. JZ SAME LDAX D CMP M JNZ NOTSAME INX H INX D JMP ILCOMPL NOTSAME MVI A,0 ;IF NOT SAME, FINISH THRU.. NSLP INX H ;..STRING SO RETURN WILL.. CMP M ;..GO TO INSTRUCTION AFTER.. JNZ NSLP ;..STRING AND NOT REMAINDER OF STRING. STC SAME POP D INX H ;AVOIDS A NOP INSTRUCTION.. XTHL ;..WHEN RETURNING. RET ENDM MFACCESS MACRO ;NO PARAMETERS USED LOCAL MOVE, CPM, MFNAME, MFN01, MFN02, MFFIX1, MFREQ LOCAL MFCUR, MOVER, SRCHF, SRCHN, STDMA, BDOS, FCB, FCBEXT LOCAL FCBRNO ;MFFLG1 IS NOT SET LOCAL BECAUSE IT MUST BE RESET ;IN MAIN MODEM PROGRAM ON AN ABORT ; ; MUST BE ASSEMBLED BY "MAC" ; ;MULTI-FILE ACCESS SUBROUTINE. ALLOWS PROCESSING ;OF MULTIPLE FILES (I.E. *.ASM) FROM DISK. THIS ;ROUTINE BUILDS THE PROPER NAME IN THE FCB EACH ;TIME IT IS CALLED. THIS COMMAND WOULD BE USED ;IN SUCH PROGRAMS AS MODEM TRANSFER, TAPE SAVE, ;ETC IN WHICH YOU WANT TO PROCESS SINGLE OR ;MULTIPLE FILES. ; ;THE FCB WILL BE SET UP WITH THE NEXT NAME, READY TO ;DO NORMAL PROCESSING (OPEN, READ, ETC.) WHEN ROUTINE IS CALLED. ; ;CARRY IS SET IF NO MORE NAMES CAN BE FOUND ; ;DEFINE DATA MOVE MACRO ; MOVE MACRO ?F,?T,?L,?I IF NOT NUL ?F LXI H,?F ENDIF IF NOT NUL ?T LXI D,?T ENDIF IF NOT NUL ?L LXI B,?L ENDIF IF NOT NUL ?I LOCAL ?B,?Z CALL ?Z ?B DB ?I ?Z POP H ;GET TO LXI B,?Z-?B ENDIF CALL MOVER MF SET -1 ;;SHOW EXPANSION ENDM ; ;DEFINE CP/M MACRO - CPM FNC,PARM ; CPM MACRO ?F,?P PUSH B PUSH D PUSH H IF NOT NUL ?F MVI C,?F ENDIF IF NOT NUL ?P LXI D,?P ENDIF CALL BDOS POP H POP D POP B ENDM ; ;------------------------------------------------ ; ; MULTI-FILE ACCESS SUBROUTINE ; ;THE ROUTINE IS COMMENTED IN PSEUDO CODE, ;EACH PSEUDO CODE STATEMENT IS IN <<...>> ; MFNAME: ;<> CPM STDMA,80H XRA A ! STA FCBEXT ;<> LDA MFFLG1 ! ORA A ! JNZ MFN01 ; <> MVI A,1 ! STA MFFLG1 ; <> MOVE FCB,MFREQ,12 ;SAVE ORIG REQ LDA FCB ! STA MFCUR ;SAVE DISK IN CURR FCB ; <> MOVE MFREQ,FCB,12 CPM SRCHF,FCB ;<> JMP MFN02 MFN01: ; <> MOVE MFCUR,FCB,12 CPM SRCHF,FCB ; <> MOVE MFREQ,FCB,12 CPM SRCHN,FCB ;<> MFN02: ;<> INR A ! STC ! JNZ MFFIX1 ! STA MFFLG1 ! RET ;FIX BY M.Z. MFFIX1: ;<> DCR A ! ANI 3 ! ADD A ADD A ! ADD A ! ADD A ! ADD A ADI 81H ! MOV L,A ! MVI H,0 PUSH H ;SAVE NAME POINTER MOVE ,MFCUR+1,11 ;<> POP H ! MOVE ,FCB+1,11 ;<> XRA A ! STA FCBEXT ! STA FCBRNO ;FIX BY M.Z. ;<> RET ; ;MULTI-FILE ACCESS WORK AREA ; MFFLG1 DB 0 ;1ST TIME SW MFREQ DS 12 ;REQ NAME MFCUR DS 12 ;CURR NAME ;------------------------------------------------ ; ;MOVE SUBROUTINE ; MOVER MOV A,M STAX D INX H INX D DCX B MOV A,B ORA C JNZ MOVER RET ; ;EQUATES USED BY MULTI-ACCESS SUBROUTINE ; SRCHF EQU 17 SRCHN EQU 18 STDMA EQU 26 ;FIX BY M.Z. BDOS EQU 5 FCB EQU 5CH FCBEXT EQU FCB+12 FCBRNO EQU FCB+32 ENDM DIRLIST MACRO ;NO PARAMETERS USED LOCAL DIRLP,PRTNAME,NOFILE,DIRDONE,QSTMARK,QSTLP,PRNTNAME,NEXTSR LOCAL MOVENAME,GETADD,DRIVE,CALCDR,SRCHFCB,NAMECT,PRNTHD,DRNAME LXI D,CMDBUF ;PUT COMMAND LINE IN FCB LXI H,5CH CALL CPMLINE LXI H,SRCHFCB CALL INITFCBS LDA 6CH ;GET DRIVE # STA SRCHFCB LDA 6DH CPI 20H ;IF BLANK GET ALL NAMES PUSH PSW CZ QSTMARK POP PSW CNZ MOVENAME ;ELSE MOVE NAME INTO FCB CALL DRIVE LXI D,80H MVI C,STDMA CALL BDOS XRA A STA NAMECT ;CR AFTER 4 NAMES LXI D,SRCHFCB MVI C,SRCHF ;DO FIRST SEARCH CALL BDOS CPI 0FFH JZ NOFILE DIRLP CALL GETADD LXI D,15 ;OFFSET FOR RECORD COUNT DAD D MOV A,M ORA A JZ NEXTSR ;NO LIST IF FILE IS ZERO LENGTH LXI D,-5 DAD D ;POINT TO $SYS ATTRIB BYTE MOV A,M ANI 80H JNZ NEXTSR ;NO LIST IF $SYS FILE LXI D,-10 DAD D ;POINT TO BEGINNING OF NAME INX H ;POINT TO FIRST LETTER LXI D,PRNTNAME MVI B,8 CALL MOVE INX D MVI B,3 CALL MOVE CALL ILPRT PRNTNAME DB ' ',' ',' ', ' | ', 0 ;8,1,3 SPACES LDA NAMECT INR A STA NAMECT ANI 03H ORA A CZ CRLF NEXTSR LXI D,SRCHFCB MVI C,SRCHN ;DO NEXT SEARCH CALL BDOS CPI 0FFH JZ DIRDONE JMP DIRLP NOFILE CALL ILPRT DB 'NOT FOUND',0 DIRDONE CALL CRLF RET QSTMARK MVI A,'?' ;IF BLANK IN FCB, PUT IN 11 ?'s MVI B,11 LXI H,SRCHFCB+1 QSTLP MOV M,A INX H DCR B JNZ QSTLP RET MOVENAME LXI H,6DH LXI D,SRCHFCB+1 MVI B,11 CALL MOVE ;MOVE IN CP/M PROGRAM RET GETADD ANI 03H ;GET MOD4 FOR CP/M 1.4 ADD A ! ADD A ! ADD A ;ADD 32 ADD A ! ADD A MOV E,A MVI D,0 LXI H,80H ;ADD DMA OFFSET DAD D RET DRIVE LDA SRCHFCB ;IF NO DRIVE, CAL ORA A ;LOGGED IN DRIVE JZ CALCDR ADI 40H JMP PRNTHD CALCDR MVI C,25 CALL BDOS ADI 41H PRNTHD STA DRNAME CALL ILPRT DB CR,LF,'DRIVE ' DRNAME DB ' ',CR,LF,0 RET SRCHFCB DS 33 NAMECT DS 1 ENDM