; ******************************************************************** ; * * ; * A PRINT UTILITY FOR CP/M 6 MARCH 80 * ; * * ; ******************************************************************** ; THIS PROGRAM PERMITS THE SIMPLE ENTRY OF "PRINT FILENAME N" ; TO PRODUCE N COPIES OF THE NAMED .PRN FILE. IF N IS NOT ; SPECIFIED. IT DEFAULTS TO 1. ; OTHER FILE TYPES MAY BE SPECIFIED IF DESIRED. TABS ARE ; EXPANDED TO 8 SPACES. AND A FORM FEED IS OUTPUT EACH 60 LINES ; AND AT THE END OF THE FILE. ;* CP/M BDOS ADDRESSES RBOOT EQU 0 ; RE-BOOT CP/M BDOS EQU 5 ; BDOS CALL ENTRY FCB EQU 5CH ; DEFAULT FILE CONTROL BLOCK FCBN EQU FCB+32 ; RECORD COUNT TYPE EQU FCB+9 ; FILE TVPE QTY EQU FCB+17 ; NUMBER OF COPIES INBUF EQU 80H ; DEFAULT DMA ADDRESS ;* CP/M BDOS FUNCTIONS READF EQU 1 ; READ CONSOLE INTO (A) TYPEF EQU 2 ; WRITE CONSOLE FROM (E) LISTF EQU 5 ; WRITE LIST DEUICE FROM (E) INTRF EQU 11 ; TEST CONSOLE INTERRUPT OPEN EQU 15 ; OPEN FILE FIND EQU 17 ; FIND FILE IN DIRECTORY READ EQU 20 ; READ FILE ;* CONTROL CHARACTERS AND CODES RUB EQU 7FH ; RUBOUT CHARACTER EOF EQU 1AH ; END OF FILE IN BUFFER TAB EQU 9 ; TAB CHARACTER FFEED EQU 0CH ; FORM FEED CHARACTER ORG 0100H ; TPA PROGRAM START ADDRESS JMP START ; GO TO PROGRAM START ;* CONSOLE I/O THROUGH BDOS CALL CI PUSH H ; SAVE REGISTERS PUSH D PUSH B MVI C,READF ; READ FUNCTION CALL BDOS ; RETURN CHAR IN (A) POP B ; RESTORE OTHER REGISTERS POP D POP H RET CO PUSH H PUSH D PUSH B MOV E,A ; PRINT CHAR TO (E) MVI C,TYPEF CALL BDOS POP B POP D POP H RET LO PUSH H PUSH D PUSH B MOV E,A MVI C,LISTF CALL BDOS MVI C,INTRF ; LOOK FOR OPERATOR CALL BDOS ; INTERRUPT ANI 1 ; IN LS BIT JZ LOX CALL CI ; IS IT A RUBOUT? CPI RUB JZ EXIT ; YES. QUIT LOX POP B POP D POP H RET CCRLF MVI A,0DH ; CR LF TO CONSOLE CALL CO MVI A,0AH JMP CO LCRLF MVI A,0DH ; CR LF TO LIST DEUICE CALL LO MVI A,0AH JMP LO MSGXP POP H ; OUTPUT MESSAGE AND RETURN MSGX1 MOV A,M ; THROUGH (H,L) CPI 0 ; TEXT TERMINATOR = 0 JZ MSGEX CALL CO INX H JMP MSGX1 MSGEX INX H ; POINT TO TEXT + 1 PCHL ; AND RETURN THERE ;* PRINT UTILITY CONSOLE MESSAGE SUBROUTINES RDMSG CALL CCRLF ; PROMPT FOR READ DISC CALL MSGXP DB 'READ DISC IN DRIVE. THEN CR ' DB 0 RDMS1 CALL CI ; GET RESPONSE CPI 'X' ; ALLOW EXIT JZ RBOOT ; BACK TO CP/M CPI 0DH ; ACCEPT CR ONLY JNZ RDMS1 CALL CCRLF ; ACKNOWLEDGE RET ; AND RETURN RDERR CALL CCRLF ; SHOW READ ERROR CALL MSGXP DB 'REAO ERROR! ENTER X TO ABORT ' DB 0DH,0AH DB ' CR TO IGNORE ' DB 0 RDER1 CALL CI ; ACCEPT CR OR X CPI 'X' JZ EXIT CPI 0DH RZ ; RETURN MEANS IGNORE JMP RDER1 ; READ ERROR EXIT CALL MSGXP DB 0DH,0AH DB 'BACK TO CP/M?' DB 0 EXIT1 CALL CI ; WAIT FOR CR OR X CPI 0DH JZ RBOOT CPI 'X' JZ RBOOT JNZ EXIT1 ; AS ONLY LEGAL RESPONSE START XRA A ; CLEAR CONTINUATION AND STA CONTD ; RELOAD FLAGS STA RELOD INR A ; DEFAULT PRINT QTY = 1 STA COUNT LXI H,TYPE ; SET FILE TYPE TO .PRN MOV A,M ; IF NOT SPECIFIED CPI ' ' JNZ START MVI M,'P' INX H MVI M,'R' INX H MVI M,'N' STAR1 LXI H,QTY ; GET PRINT QUANTITY MOV A,M ; IF ANY CPI ' ' JZ PRNIN ; ELSE CONTINUE SUI 30H ; STRIP ASCII STA COUNT ; AND SAVE QUANTITY INX H MOV A,M ; ANOTHER DIGIT? CPI ' ' JZ PRNIN ; NO. CONTINUE CALL MULTI ; YES. COUNT * 10 > (C) MOV A,M ; ADD NEW LS DIGIT SUI 30H ADD C STA COUNT ; FOR TOTAL INX H MOV A,M ; GET LAST DIGIT CPI ' ' ; IF ANY JZ PRNIN CALL MULTI MOV A,M SUI 30H ADD C STA COUNT ;* INPUT THE PRINT FILE PRNIN CALL CCRLF ; SIGN ON MESSAGE CALL MSGXP DB 'CP/M PRINT UTILITYV V80.0 6 MAR 80' DB 0DH,0AH DB 0 CALL RDMSG ; PROMPT FOR READ DISC LXI D,FCB ; LOOK FOR FILE MVI C,FIND ; BEFORE GOING AHEAD CALL BDOS CPI 255 ; DOES FILE EXIST? JNZ PRNI1 ; YES. READ IT CALL CCRLF ; NO. GIVE UP CALL MSGXP DB 'FILE DOES NOT EXIST! ' DB 0 JMP EXIT PRNI1 LXI H,0 ; ZERO LINE AND SHLD DSAVE ; CHAR COUNTERS LXI H,BUFFR ; INITIALIZE POINTER SHLD HSAVE ; INTO BUFFER LXI D,FCB ; USE FILE CONTROL BLOCK MVI C,OPEN ; AND OPEN THE FILE CALL BDOS CPI 255 ; ERROR? JNZ PRNI2 CALL CCRLF ; YES. SHOW IT DB 'UNABLE TO OPEN FILE! ' DB 0 JMP EXIT ; AND ABORT PRNI2 LXI D,FCB ; READ A RECORD MVI C,READ CALL BDOS CPI 0 ; GOOD READ? JZ PRNI3 ; YES. STORE IT CPI 1 ; OR END OF FILE? JZ RDEND ; YES CALL RDERR ; NO, SHOW ERROR PRNI3 LHLD HSAVE ; STORE THE RECORD LXI D,INBUF MVI C,80H PRNI4 LDAX D MOV M,A INX H INX D DCR C JNZ PRNI4 SHLD HSAVE ; AND NEXT ADDRESS LDA 7 ; ANY MEMORY LEFT? DCR A CMP H JNZ PRNI2 ; YES, KEEP READING XRA A ; NO. SET FLAGS CMA STA CONTD ; AND STA RELOD JMP RDEN1 ; PRINT PARTIAL FILE RDEND XRA A ; CLEAR CONTINUED STA CONTD ; FLAG STA FCBN ; REWIND THE FILE RDEN1 LHLD HSAVE ; FLAG END OF FILE MVI M,EOF ;* PRINT THE FILE PRNOU LHLD DSAVE ; (E) = POSITION ON LINE XCHG ; (D) = LINE COUMT ON PAGE LXI H,BUFFR ; OUTPUT THE BUFFER PRNO1 MOV A,M ; GET A CHARACTER INX H ; AND POINT TO NEXT CPI EOF ; ALL DONE? JZ PRNEX CPI 0AH ; IGNORE LINE FEEDS JZ PRNO1 CPI 0DH ; CARRIAGE RETURN? JZ NXTLN CPI TAB ; TAB CHARACTER? JZ TABBR ; YES, SKIP AHEAD CPI 1FH ; NON-PRINTING? JC PRNO2 ; YES. DONT COUNT IT INR E ; NO. COUNT PRNO2 CALL LO ; WRITE THE CHARAACTER JMP PRNO1 NXTLN CALL LCRLF ; CR AND LF MVI E,0 ; ZERO CHAR COUNTER INR D ; COUNT LINE MOV A,D ; TO END OF PAGE CPI 60 CZ FORMO ; THEN FORM FEED JMP PRNO1 ; AND CONTINUE PRNEX XCHG ; SAVE COUNTERS SHLD DSAVE LDA CONTD ; FILE CONTINUED? ORA A JZ PRNE1 ; NO, COUNT IT LXI H,BUFFR ; YES. READ MORE SHLD HSAVE JMP PRNI2 PRNE1 MVI A,FFEED ; FEED OUT LAST PAGE CALL LO LXI H,0 ; AND ZERO COUNTERS SHLD DSAVE LDA COUNT ; COUNT THIS PRINTOUT DCR A STA COUNT JNZ PRNE2 ; AND DO MORE TIL CALL MSGXP ; ALL DONE DB 'ALL DOME! ' DB 0 JMP EXIT PRNE2 LDA RELOD ; HAUE TO RELOAD FILE? ORA A JZ PRNOU ; NO, PRINT IT AS IS XRA A ; YES. CLEAR THE FLAG STA RELOD JMP PRNI1 ; AND RE-OPEN THE FILE TABBR MOV A,E ; GET POSITION ANI 07 ; MASK 3 LS BITS MOV C,A ; FOR TAB SPACING TABB1 MOV A,C ; DONE? ANI 8 JNZ PRNO1 ; YES. NEXT CHARACTER MVI A,' ' CALL LO ; NO. OUTPUT A SPACE INR E ; COUNT IT INR C JMP TABB1 ; AND LOOP FORMO MVI A,FFEED ; OUTPUT A FORM FEED CALL LO MVI D,0 ; ZERO LINE COUNT RET MULTI LDA COUNT ; COUNT TIMES TEN MOV C,A RLC RLC RLC ADD C ADD C MOV C,A ; INTO (C) RET ;* RAM BUFFERS HSAVE DS 2 ; BUFFER ADDRESS STORE DSAVE DS 2 ; COUNTERS STORE CONTD DS 1 ; CONTINUED FLAG RELOD DS 1 ; RELOAD FILE FLAG COUNT DS 1 ; NUMBER TO PRINT BUFFR DS 1 ; START OF RAM BUFFER END