;-----------------------------------------------; ; ; ; CP/M 8080 UTILITY PACKAGE ; ; ; ;-----------------------------------------------; ; ;REV 0 12-JULY-77 MGL ; ;REV 1 12-SEPT-80 Keith Petersen, W8SDZ ; (to clean up format of file) ; ;JUMP TABLE ; ORG 103H ;FOR CP/M LOAD VIA DDT JMP WLINE ;WRITE LINE ON LIST DEVICE JMP WMSG ;WRITE LINE ON CONSOLE DEVICE JMP DSKSEL ;SELECT DISK JMP OPNFIL ;OPEN FILE JMP CLSFIL ;CLOSE FILE JMP DELFIL ;DELETE FILE JMP DREAD ;DISK READ (USING CP/M) JMP DWRITE ;DISK WRITE(USING CP/M) JMP CREFIL ;CREATE FILE JMP DMASET ;SET DMA ADDRESS JMP MOVE ;MOVE BYTES JMP CMPCHR ;COMPARE BYTES JMP CMPHD ;COMPARE HL : DE JMP MUL16 ;HL <= HL * DE (16 BITS ONLY) JMP GNB ;GET NEXT BYTE (1K BUFFERING) (USING FCB1) JMP WNB ;WRITE NEXT BYTE (USING FCB1) JMP GNB2 ;GET NEXT BYTE (USING FCB2) JMP WNB2 ;WRITE NEXT BYTE (USING FCB2) JMP CNV2HX ;CONVERT A REG TO HEX IN BUFFER (HL) ;-----------------------------------------------; ; ; ; COMMUNICATIONS AREA ; ; ; ;-----------------------------------------------; ; FCB1 DB 0 ;FILE CONTROL BLOCK #1 DS 32 ;REMAINING AREA FCB2 DB 0 ;FILE CONTROL BLOCK #2 DS 32 IBP DS 2 ;INPUT BUFFER POINTER (FCB1) IBP2 DS 1 ;INPUT BUFFER POINTER (FCB2) OBP DS 1 ;OUTPUT BUFFER POINTER (FCB1) OBP2 DS 1 ;OUTPUT BUFFER POINTER (FCB2) IBUF DW INBUF ;INPUT BUFFER ADDRESS OBUF DW OUTBUF ;OUTPUT BUFFER ADDRESS IBUF2 DW INBUF2 ;INPUT BUFFER ADDRESS (FCB2) OBUF2 DW OUTBF2 ;OUTPUT BUFFER ADDRESS (FCB2) INBUF DS 1024 ;1K BUFFER FOR GNB (TO SPEED UP INPUT STREAM) OUTBUF DS 128 ;I/O BUFFERS INBUF2 DS 128 OUTBF2 DS 128 ; ;CP/M EQUATES ; BDOS EQU 5 BOOT EQU 0 ; ; ;ENTRY - USED TO CALL BDOS - SAVES AND RESTORES REGISTERS ; ENTRY PUSH B PUSH D PUSH H CALL BDOS POP H POP D POP B RET ; ;WLINE - WRITE LINE TO LIST DEVICE ;HL -> BUFFER, TERM = 0AH ; WLINE MOV A,M MOV E,A MVI C,5 CALL ENTRY MOV A,M CPI 0AH RZ INX H JMP WLINE ; ;WMSG - WRITE MESSAGE TO CONSOLE ; ;DE -> MSG, TERM-'$' ; WMSG MVI C,9 CALL ENTRY RET ; ;DSKSEL - SELECT DISK ;DRIVE NUMBER IN A REG ; DSKSEL MOV E,A MVI C,14 CALL ENTRY RET ; ;OPNFIL - OPEN FILE CONTROL BLOCK ;REEL # AND NR ARE SET TO 00H ;DE -> FCB ;Z=0 SUCCESS, Z=1 FAILURE ; OPNFIL PUSH H LXI H,12 DAD D MVI M,0 ;ZERO REEL # MVI C,15 PUSH D CALL ENTRY POP D CPI 255 POP H RZ PUSH H LXI H,32 DAD D MVI M,0 ; ZERO NR POP H RET ; ;CLSFIL - CLOSE FILE CONTROL BLOCK ;DE -> FCB ;Z=1 ERROR, Z=0 SUCCESS ; CLSFIL MVI C,16 CALL ENTRY CPI 255 RET ; ;DELFIL - DELETE FILE ;DE -> FCB ;Z=1 ERROR, Z=0 SUCCESS ; DELFIL MVI C,19 CALL ENTRY CPI 255 RET ; ;DREAD - READ DISK SECTOR ;DE -> FCB ;Z=0 ERROR OR EOF, Z=1 NORMAL ; DREAD MVI C,20 CALL ENTRY CPI 0 RET ; ;DWRITE - WRITE DISK SECTOR ;DE -> FCB ;Z=0 ERROR, Z=1 NORMAL ; DWRITE MVI C,21 CALL ENTRY CPI 0 RET ; ;CREFIL - CREATE FILE ; ;REEL # ASSUMMED TO BE SET ; ;DE -> FCB ;Z=0 NORMAL, Z=1 ERROR ; CREFIL MVI C,22 CALL ENTRY CPI 255 RET ; ;DMASET - SET DMA ADDRESS ; ;BUFFER ADDRESS IN DE ; DMASET MVI C,26 CALL ENTRY RET ; ;MOVE (HL) <= (DE) LEN IN BC ; MOVE XCHG ; MOVLOP MOV A,M STAX D INX H INX D DCX B MOV A,B ORA C JNZ MOVLOP XCHG ;PUT REGS BACK FOR CALLING ROUTINES SAKE RET ; ;CMPCHR - COMPARE STRINGS (HL) : (DE) LEN IN B ; CMPCHR PUSH H PUSH D PUSH B ;SAVE REGS LDAX D CMP M JNZ CMPCH1 INX H INX D DCR B JNZ CMPCHR+3 ; CMPCH1 POP B POP D POP H ;RESTORE REGS RET ; ;MUL16 - HL <= HL * DE (16 BITS ONLY) ; MUL16 PUSH B PUSH D POP B PUSH D XCHG LXI H,0 ; MUL16A MOV A,C ORA B JNZ MUL16B POP D POP B RET ; MUL16B DAD D DCX B JMP MUL16A ; ;CMPHD - COMPARE HL:DE ; CMPHD MOV A,H CMP D RNZ MOV A,L CMP E RET ; ;GNB - GET NEXT BYTE (FCB1) ; GNB PUSH H PUSH D LHLD IBP LXI D,INBUF+1024 CALL CMPHD ;SEE IF END OF BUFFER POP D POP H JNZ GNB0 ;BRANCH IF NOT AT END OF BUFFER PUSH H PUSH D PUSH B ;GET 1K BLOCK FROM DISK LXI H,INBUF SHLD GNBPTR ;SET UP POINTER FOR DMASET MVI B,8 ;NUMBER OF 128 BYTE SECTORS IN 1K BUFFER ; GNB0A PUSH B LHLD GNBPTR XCHG CALL DMASET ;SET UP DMA ADDRESS LXI D,FCB1 CALL DREAD ;GO READ A SECTOR LHLD GNBPTR LXI D,128 DAD D SHLD GNBPTR ;UPDATE POINTER POP B DCR B JNZ GNB0A ;BRANCH BACK IF MORE TO DO POP B POP D ;RESTORE REGS LXI H,INBUF SHLD IBP POP H ;SET UP NEXT DATA POINTER ; GNB0 PUSH H LHLD IBP MOV A,M INX H SHLD IBP POP H ;GET BYTE RET ; GNBPTR DS 2 ;TEMP POINTER FOR BUFFERING ; ;GNB2 - GET NEXT BYTE (FCB2) ; GNB2 PUSH D LDA IBP2 CPI 80H JNZ GNB20 PUSH H PUSH B LXI D,INBUF2 CALL DMASET LXI D,FCB2 CALL DREAD POP B POP H XRA A ; GNB20 MOV E,A MVI D,0 INR A STA IBP2 PUSH H LXI H,INBUF DAD D MOV A,M POP H POP D RET ; ;WNB - WRITE NEXT BYTE (FCB1) ;BYTE IN A REG ; WNB PUSH H PUSH D PUSH PSW LDA OBP CPI 80H JNZ WNB0 LXI D,OUTBUF CALL DMASET LXI D,FCB1 CALL DWRITE JZ WNB00 ;BRANCH IF OK LXI D,WNBERR CALL WMSG JMP BOOT ; WNB00 XRA A ; WNB0 MOV E,A MVI D,0 INR A STA OBP LXI H,OUTBUF DAD D POP PSW MOV M,A POP D POP H RET ; WNBERR DB 13,10,'OUTPUT FILE WRITE ERROR ' DB '(DISK MAY BE FULL)',13,10,'$' ; ;WNB2 - WRITE NEXT BYTE (FCB2) ; WNB2 PUSH H PUSH D PUSH PSW LDA OBP2 CPI 80H JNZ WNB20 LXI D,OUTBF2 CALL DMASET LXI D,FCB2 CALL DWRITE JZ WNB200 ;BRANCH IF ALL OK LXI D,WNBERR CALL WMSG JMP BOOT ; WNB200 XRA A ; WNB20 MOV E,A MVI D,0 INR A STA OBP2 LXI H,OUTBF2 DAD D POP PSW MOV M,A POP D POP H RET ; ;CNV2HX - CONVERT CONTENTS OF A REG TO HEX CHARACTERS ;AND PLACE IN BUFFER POINTED TO BY HL ; CNV2HX PUSH B MOV B,A RRC RRC RRC RRC ANI 0FH CALL CNV2H MOV A,B POP B ANI 0FH ; CNV2H CPI 0AH JC CNV2H1 ADI 7 ; CNV2H1 ADI '0' MOV M,A INX H RET ; ;END OF FILE CPMUTIL.ASM ;