* PROGRAM NAME: PRINT II * AUTHOR: RICHARD CONN * DATE: 27 JUNE 82 * VERSION: 3.5 * PREVIOUS VERSION: 3.4 (19 MAY 82) * 3.1 (30 APR 82), 3.2 (1 MAY 82), 3.3 (8 MAY 82) * 2.3 (10 OCT 81), 2.4 (11 OCT 81), 3.0 (7 MAR 82) * 2.2 (5 OCT 81), 2.1 (10 MAR 81), 2.0 (19 OCT 80) * 1.6 (14 JUL 80), 1.5 (28 JUN 80), 1.4 (22 JUN 80) * 1.3 (24 MAY 80), 1.2 (31 JAN 80), 1.1 (14 DEC 79) * * NOTE: Access to the clock can be gained by overlaying the PRINT2.COM * with the SPTTIME.HEX file generated by assembling SPTTIME.ASM * with the PRINT2 option set to TRUE. * VERS EQU 35 ; Version Number * * CP/M EQUATES * BASE EQU 0 ; BASE ADDRESS FOR CP/M ENTRY EQU BASE+5 ; BDOS ENTRY POINT TFCB EQU BASE+5CH ; FCB TBUFF EQU BASE+80H ; BUFFER TPA EQU BASE+100H ; BEGINNING OF TPA * * ASCII EQUATES * CR EQU 0DH ; CARRIAGE RETURN CHAR LF EQU 0AH ; LINE FEED CHAR BS EQU 8 ; BACKSPACE CHAR TAB EQU 9 ; TAB CHAR SPACE EQU ' ' ; SPACE CHAR FF EQU 12 ; FORM FEED CHAR CTRLC EQU 'C'-'@' ; CONTROL-C XON EQU 'Q'-'@' ; ^Q=X-ON XOFF EQU 'S'-'@' ; ^S=X-OFF CTRLZ EQU 'Z'-'@' ; CONTROL-Z CTRLI EQU 'I'-'@' ; CONTROL-I (TAB CHAR) INTC1 EQU 'C'-'@' ; CTRL-C = ABORT INTC2 EQU 1BH ; = ABORT LXID EQU 11H ; LXI D,XX INSTR MVIA EQU 3EH ; MVI A,X INSTR ********************************************************* * * * PRINT -- PRINTS THE FILE SPECIFIED IN PAGED FORMAT * * ON THE SUPPORT PACKAGE TTY DEVICE IF THE * * PACKAGE IS INSTALLED OR ON THE CP/M LST: DEVICE * * * * THE FORM OF THE PRINT COMMAND IS: * * PRINT X:FILENAME.EXT * * /C * * /E * * /F * * /H HEADING TEXT * * /L * * /M * * /N * * /Pn1,n2 * * /Sn * * /T * * ONLY 'FILENAME.EXT' IS REQUIRED. * * * * THE OPTIONS FOR THE PRINT COMMAND ARE: * * 1) /H -- DEFINE HEADING TO BE PRINTED AT THE * * TOP OF EACH PAGE. THE OPTION INDICATOR '/H' * * IS FOLLOWED IMMEDIATELY BY A DELIMITER, * * THE TEXT OF THE HEADING, AND THE SAME * * DELIMITER TO TERMINATE THE HEADING TEXT. * * 2) /S -- SKIP TO THE SPECIFIED PAGE. THE * * OPTION INDICATOR '/S' IS FOLLOWED * * IMMEDIATELY BY A NUMBER FROM 1 TO 65535 * * WHICH GIVES THE NUMBER OF THE PAGE TO SKIP * * TO. * * 3) /L -- NUMBER EACH LINE OF SOURCE. THIS * * OPTION HAS NO ARGUMENTS, AND IT FUNCTIONS TO * * PLACE A NUMBER FOLLOWED BY A COLON AT THE * * BEGINNING OF EACH LINE OF SOURCE. * * 4) /N -- TURN OFF PAGE NUMBERING. * * 5) /Pn1,n2 -- SET PAGE PARAMETERS. n1 IS THE * * NUMBER OF LINES OF TEXT PER PAGE, AND n2 IS * * THE NUMBER OF PHYSICAL LINES ON A PAGE. n2 * * IS OPTIONAL. * * 6) /C -- DISPLAY/ALTER ENVIRONMENT AND SAVE ON * * DISK * * 7) /E -- EXACT MODE; EXPAND TABS, COUNT LINES, * * AND RECOGNIZE FORM FEEDS ONLY (USE COUNT OF * * PHYSICAL LINES PER PAGE ONLY) * * 8) /T -- TIME DISPLAY TOGGLE * * 9) /F -- FILE NAME DISPLAY TOGGLE * * 10) /M -- MULTIPLE RUN TOGGLE * * (SUPPRESS SET TOF MESSAGE) * * * * IN ALL CASES, TABS ARE EXPANDED AS PER THE CP/M * * CONVENTION (1, 8, 15, ...). * * * ********************************************************* * ********************************************************* * START OF PRINT PROGRAM * ********************************************************* ORG 100H JMP START ********************************************************* * CUSTOMIZATION PARAMETERS -- SIZE OF PAGE * * SET FOR TTY, MODEL 43 * ********************************************************* FILE$NAME: DB 0,'PRINT COM',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DB 0,0,0,0,0,0 LPP: DB 51 ; NUMBER OF PHYSICAL LINES/PAGE LPPT: DB 45 ; NUMBER OF LINES OF TEXT PER PAGE CHARS$PER$LINE: DB 132 ; NUMBER OF CHARS/LINE OPTC: DB '/' ; OPTION DELIMITER CHAR TDISP: DB 0FFH ; TURN ON TIME DISPLAY EXACT: DB 0 ; TURN OFF EXACT MODE NCHK: DB 0 ; LINE NUMBER DISPLAY FLAG; 0=NO; TURN OFF LNUM DISP FFLG: DB 0 ; FORM FEED FLAG; 0=NO; TURN OFF FORM FEED CHAR FNFLG: DB 0FFH ; FILE NAME FLAG; TURN ON FILE NAME DISPLAY PNFL: DB 0FFH ; PAGE NUMBERING FLAG; 0=NO; TURN ON PAGE NUMBERING MFLG: DB 0FFH ; MULTIPLE RUN (NO TOF MSG); 0=NO; TURN OFF TOF, ON MR NHEAD EQU 80 ; 80 CHARS IN HEADING MAX HBUF: DB 0 ; HEADING BUFFER DS NHEAD ; 0=END OF BUFFER START: LXI SP,STACK ; RESET STACK POINTER MVI A,0FFH ; TURN OFF LOGIN FLAG STA LFLG LXI H,1 SHLD PNUM ; INIT PAGE COUNT SHLD LNUM ; INIT LINE COUNT * * PLACE 0 AT END OF STRING * LXI H,TBUFF MOV A,M ADD L ; HL PT TO LAST BYTE MOV L,A MOV A,H ACI 0 MOV H,A INX H ; HL PT TO AFTER LAST BYTE MVI M,' ' ; TRAILING INX H MVI M,0 ; EOL INDICATOR PLACED * * EXTRACT DRIVE SPECIFICATION * LXI H,TBUFF+1 ; SCAN TBUFF FOR DRIVE SPECIFICATION XRA A ; A=0 STA LFLG2 ; ASSUME NO DRIVE SPEC DIDSKP: MOV A,M ; SKIP UNTIL NON-BLANK INX H ; PT TO NEXT CPI ' ' JZ DIDSKP DIDENT: MOV A,M ; SCAN FOR DRIVE IDENT INX H ; PT TO NEXT CHAR CPI ':' JNZ BINIT DID1: DCX H ; GET DRIVE LETTER DCX H MOV A,M SUI 'A' ; CONVERT A=0, B=1, C=2, D=3 CPI 4 ; ERROR? JC DID2 CALL PRINT$MESSAGE DB CR,LF,'ERROR -- Bad Drive Spec',0 JMP EXIT DID2: PUSH PSW ; SAVE NEW DRIVE NUMBER MVI C,25 ; GET CUR DRIVE NUMBER CALL ENTRY STA LFLG ; SAVE NUMBER POP PSW ; GET NEW DRIVE NUMBER ORI 80H ; SET MSB STA LFLG2 ; SAVE DRIVE NUMBER TO LOG INTO * * INITIALIZE HEADING BUFFER * BINIT: LXI H,HBUF ; HEADING IN HBUF MVI A,NHEAD ; NUMBER OF CHARS PERMITTED IN BUFFER CALL BOPEN ; OPEN BUFFER CALL SP$TIME ; GET TIME SUPPORT INDICATOR (IN A) AND PTR TO STR (HL) SHLD TIME$STR ; SAVE STRING PTR STA TIME$SPT ; SUPPORT FLAG * * EXTRACT OPTIONS AND LOAD APPROPRIATE BUFFERS * OPTION: LXI H,TBUFF+1 ; LOOK FOR OPTIONS XRA A ; A=0 STA SKFL ; SET NO SKIP STA SAVE$FLAG ; SET NO SAVE OPT1: LDA OPTC ; GET OPTION CHAR MOV B,A ; ... IN B MOV A,M ; OPTION? INX H ; PT TO NEXT CMP B JZ OPT2 ORA A ; EOLN? JNZ OPT1 JMP OPEN * * THIS ROUTINE WRITES THE PRINT.COM FILE BACK TO DISK * OPTWR: CALL PRINT$MESSAGE DB CR,LF,'Writing ',0 CALL PRINT$FILE$NAME CALL PRINT$MESSAGE DB ' to Disk',0 XRA A ; ZERO RECORD COUNT STA FILE$NAME+32 LXI D,FILE$NAME ; OPEN FILE MVI C,19 ; DELETE FILE PUSH D ; SAVE PTR TO FCB CALL ENTRY POP D ; GET PTR TO FCB MVI C,22 ; MAKE FILE CALL ENTRY CPI 255 ; ERROR? JZ OPT3 ; ABORT CALL SP$END ; GET END OF SUPPORT PACKAGE MOV B,H ; NUMBER OF PAGES DCR B ; ... -1; B=NUMBER OF PAGES MOV A,B ; DOUBLE IT FOR NUMBER OF SECTORS ADD B MOV B,A ; B=NUMBER OF 128-BYTE SECTORS LXI H,TPA ; STARTING ADDRESS OPTWR1: LXI D,TBUFF ; TO DISK OPT2A: MOV A,M ; GET BYTE STAX D ; PUT BYTE INX H ; PT TO NEXT INX D MOV A,E ; GET LOW-ORDER ORA A ; ZERO? JNZ OPT2A PUSH H PUSH B ; SAVE REGS LXI D,FILE$NAME MVI C,21 ; WRITE SECTOR CALL ENTRY ORA A ; 0=OK JNZ OPT3 POP B POP H ; GET REGS DCR B ; COUNT DOWN JNZ OPTWR1 LXI D,FILE$NAME MVI C,16 ; CLOSE FILE CALL ENTRY CALL PRINT$MESSAGE DB CR,LF,'PRINT Save Complete -- Returning to CP/M',0 JMP EXIT OPT3: CALL PRINT$MESSAGE DB CR,LF,'File Write Error -- Unsuccessful Save',0 JMP EXIT * * OPTION DETECTED * OPT2: MOV A,M ; GET CHAR LXI D,CMD$TABLE ; SCAN COMMAND TABLE CALL EXEC$CMD CALL PRINT$ID ; PRINT PROGRAM ID LXI D,OPTER ; INVALID OPTION CALL CPRINT JMP EXIT * * SCAN COMMAND TABLE PTED TO BY DE FOR CMD IN A * EXEC$CMD: MOV B,A ; COMMAND IN B EXEC$CMD1: LDAX D ; GET NEXT CHAR ORA A ; 0=DONE=NOT FOUND RZ CMP B ; MATCH? JZ EXEC$CMD2 INX D ; SKIP CMD INX D ; SKIP ADR INX D JMP EXEC$CMD1 EXEC$CMD2: INX D ; PT TO CMD LDAX D ; GET LOW-ORDER MOV C,A ; ... IN C INX D ; GET HIGH LDAX D MOV B,A POP D ; CLEAR STACK PUSH B ; SAVE EXEC ADR ON STACK RET ; GO! * * CONFIGURATION OPTION * OPTCONFIG: CALL DISPLAY$ENVIRONMENT ; DISPLAY SETTINGS CALL PRINT$MESSAGE DB CR,LF,LF,' Configuration Command? ',0 MVI C,1 ; INPUT FROM CON: CALL ENTRY ; GET RESPONSE CALL CAPS ; CAPITALIZE LXI D,CONFIG$CMD CALL EXEC$CMD ; EXECUTE COMMAND LXI D,CMDERR ; OPTION ERROR CALL CPRINT JMP OPTCONFIG * SET FILE NAME CF$FNAME: CALL PRINT$MESSAGE DB CR,LF,' New Name of PRINT File (=No Change)? ',0 LXI D,INPBUF ; INPUT INTO BUFFER MVI C,10 ; READLN CALL ENTRY LXI H,INPBUF+1 ; PT TO CHAR COUNT MOV C,M ; ... IN C INX H ; PT TO FIRST CHAR MOV A,C ; GET CHAR COUNT ORA A ; 0=NO CHANGE JZ OPTCONFIG LXI D,FILE$NAME+1 ; COPY INTO FILE NAME FCB MVI A,0FFH ; SET NO EOL STA EOL$FLAG MVI B,8 ; 8 CHARS TO FILE NAME CALL CF$FNAME0 MVI B,3 ; 3 CHARS TO FILE TYPE LXI D,FILE$NAME+9 ; COPY INTO FILE NAME TYPE FCB CALL CF$FNAME0 JMP OPTCONFIG CF$FNAME0: LDA EOL$FLAG ; GET EOL FLAG ORA A ; 0=EOL RZ PUSH D PUSH B MVI A,' ' ; FILL CF$FNAME0X: STAX D ; STORE INX D DCR B JNZ CF$FNAME0X POP B POP D CF$FNAME1: MOV A,M ; GET CHAR CALL CAPS ; CAPITALIZE CPI '.' ; END OF TYPE? JZ CF$FNAME2 STAX D ; STORE CHAR INX H ; PT TO NEXT INX D DCR C ; COUNT DOWN CHARS JZ CF$FNAME$EOL DCR B ; COUNT DOWN CHARS JNZ CF$FNAME1 MOV A,M ; MUST BE DECIMAL OR EOL CPI '.' ; DECIMAL? JNZ CF$FNAME$ERROR CF$FNAME2: INX H ; PT TO NEXT DCR C ; COUNT DOWN CHARS CF$FNAME$EOL: MOV A,C ; SET EOL FLAG STA EOL$FLAG RET CF$FNAME$ERROR: CALL PRINT$MESSAGE DB CR,LF,' Invalid File Name Specification -- Reenter',0 POP D ; CLEAR STACK JMP CF$FNAME * SET CHARACTER COUNT CF$CHAR: CALL PRINT$MESSAGE DB CR,LF,' Number of Characters/Line (=No Change)? ',0 CALL DECIN ; DECIMAL INPUT ORA A ; NO CHANGE? JZ OPTCONFIG STA CHARS$PER$LINE ; SET VALUE JMP OPTCONFIG * TOGGLE MULTIPLE RUN FLAG CF$MRF: LDA MFLG ; GET FLAG CMA STA MFLG JMP OPTCONFIG * TOGGLE FILE NAME INCLUSION CF$FNF: LDA FNFLG ; GET FLAG CMA STA FNFLG JMP OPTCONFIG * TOGGLE FORM FEED FLAG CF$FORM: LDA FFLG ; GET FLAG CMA STA FFLG JMP OPTCONFIG * TOGGLE EXACT MODE CF$EXACT: LDA EXACT ; GET FLAG CMA STA EXACT JMP OPTCONFIG * TOGGLE TIME DISPLAY CF$TIME: LDA TDISP ; GET FLAG CMA STA TDISP JMP OPTCONFIG * TOGGLE LINE NUMBERING CF$LINE: LDA NCHK ; GET FLAG CMA STA NCHK JMP OPTCONFIG * TOGGLE PAGE NUMBERING CF$PAGE: LDA PNFL ; GET FLAG CMA STA PNFL JMP OPTCONFIG * SET TEXT/PHYSICAL LINE COUNTS CF$NUM: CALL PRINT$MESSAGE DB CR,LF,' Number of Text Lines/Page (=No Change)? ',0 CALL DECIN ; DECIMAL INPUT ORA A ; NO CHANGE? JZ CF$NUM1 STA LPPT ; SET CONSTANT CF$NUM1: CALL PRINT$MESSAGE DB CR,LF,' Number of Physical Lines/Page (=No Change)? ',0 CALL DECIN ; DECIMAL INPUT ORA A ; NO CHANGE? JZ OPTCONFIG STA LPP ; SET CONSTANT JMP OPTCONFIG * * INPUT DECIMAL CHARS UNTIL ENCOUNTERED * DECIN: LXI D,INPBUF ; NUMBER BUFFER MVI C,10 ; READLN CALL ENTRY LXI H,INPBUF+1 ; PT TO CHAR COUNT MOV C,M ; CHAR COUNT IN C INX H ; PT TO FIRST CHAR MVI D,0 ; SET ACCUMULATED VALUE TO ZERO MOV A,C ; ANY CHARS? ORA A ; 0? JZ DECIN$DONE DECIN$LOOP: MOV A,M ; GET DIGIT SUI '0' ; CONVERT TO BINARY JC DECIN$ERROR CPI 10 ; RANGE? JNC DECIN$ERROR INX H ; PT TO NEXT MOV E,A ; SAVE VALUE IN E MOV A,D ; VALUE IN A ADD A ; A=A*2 JC DECIN$RANGE ; RANGE ERROR ADD A ; A=A*4 JC DECIN$RANGE ADD D ; A=A*5 JC DECIN$RANGE ADD A ; A=A*10 JC DECIN$RANGE ADD E ; A=A*10+E MOV D,A ; RESULT IN D JC DECIN$RANGE DCR C ; COUNT DOWN JNZ DECIN$LOOP DECIN$DONE: MOV A,D ; RESULT IN A RET DECIN$ERROR: CALL PRINT$MESSAGE DB CR,LF,'Invalid Decimal Number -- Reenter: ',0 JMP DECIN DECIN$RANGE: CALL PRINT$MESSAGE DB CR,LF,'Numeric Overflow -- Value > 255 -- Reenter: ',0 JMP DECIN * * PRINT NAME OF FILE * PRINT$FILE$NAME: LXI H,FILE$NAME+1 ; PT TO NAME MVI B,8 ; 8 CHARS CALL PRFN MVI A,'.' CALL CONOUT MVI B,3 ; 3 CHARS CALL PRFN RET PRFN: MOV A,M ; GET CHAR CALL CONOUT INX H ; PT TO NEXT DCR B ; COUNT DOWN JNZ PRFN RET * * CAPITALIZE CHAR IN A * CAPS: ANI 7FH ; MASK OUT MSB CPI 61H ; SMALL A? RC CPI 7BH ; LESS THAN SMALL Z? RNC ANI 5FH ; CAPITALIZE RET * * DISPLAY ENVIRONMENT * DISPLAY$ENVIRONMENT: CALL PRINT$MESSAGE DB CR,LF,'++ PRINT II Configuration Display ++',0 LDA TIME$SPT ; IS TIME SUPPORTED? ORA A ; 0=NO JZ DE1 CALL PRINT$MESSAGE DB CR,LF,'Support Package is Installed -- Clock is Available',0 JMP DE2 DE1: CALL PRINT$MESSAGE DB CR,LF,'Support Package is NOT Installed -- Clock is not ' DB 'Available',0 DE2: CALL PRINT$MESSAGE DB CR,LF DB CR,LF,'Cmd Function' DB CR,LF,'--- --------' DB CR,LF,'^C Abort to CP/M' DB CR,LF,' C Number of Characters/Line = ',0 LDA CHARS$PER$LINE CALL NUM$PRNT CALL PRINT$MESSAGE DB CR,LF,' E Exact Mode is ',0 LDA EXACT ; GET EXACT MODE FLAG CALL YN$PRNT CALL PRINT$MESSAGE DB CR,LF,' F Form Feed is ',0 LDA FFLG ; GET FORM FEED FLAG CALL YN$PRNT CALL PRINT$MESSAGE DB CR,LF,' G File Name Display is ',0 LDA FNFLG ; GET FILE NAME FLAG CALL YN$PRNT CALL PRINT$MESSAGE DB CR,LF,' L Numbering of Lines is ',0 LDA NCHK ; LINE NUMBERING CALL YN$PRNT CALL PRINT$MESSAGE DB CR,LF,' M Multiple Run Flag is ',0 LDA MFLG ; MULTIPLE RUN CALL YN$PRNT CALL PRINT$MESSAGE DB CR,LF,' N Number of Text Lines/Page = ',0 LDA LPPT ; NUMBER OF TEXT LINES CALL NUM$PRNT CALL PRINT$MESSAGE DB CR,LF,' Number of Physical Lines/Page = ',0 LDA LPP ; NUMBER OF PHYSICAL LINES CALL NUM$PRNT CALL PRINT$MESSAGE DB CR,LF,' P Numbering of Pages is ',0 LDA PNFL ; PAGE NUMBERING CALL YN$PRNT CALL PRINT$MESSAGE DB CR,LF,' T Time Display is ',0 LDA TDISP ; TIME DISPLAY CALL YN$PRNT CALL PRINT$MESSAGE DB CR,LF,' X Exit to CP/M and Rewrite PRINT to Disk' DB CR,LF,' Y Change Name of PRINT File from ',0 CALL PRINT$FILE$NAME CALL PRINT$MESSAGE DB CR,LF,LF,'++ End of Configuration Display ++',CR,LF,0 RET * PRINT YES OR NO DEPENDING ON REG A (A=0 MEANS NO) YN$PRNT: ORA A ; 0=NO JZ NO$PRNT CALL PRINT$MESSAGE DB 'On',0 RET NO$PRNT: CALL PRINT$MESSAGE DB 'Off',0 RET * PRINT TO CON: CPRINT: MVI C,9 ; PRINT ON CON: JMP ENTRY * PRINT STRING PTED TO BY RET ADR ON CON: PRINT$MESSAGE: XTHL ; SAVE HL MVI C,0 ; SET TAB COUNT CPMSG: MOV A,M ; GET CHAR ANI 7FH ; MASK OUT MSB INX H ; PT TO NEXT ORA A ; 0=DONE JZ CPMSG$DONE CPI TAB ; TABULATE? JZ CPMSG$TAB CPI CR ; NEW LINE? JZ CPMSG$CR CALL CONOUT ; PRINT TO CON: CPI ' ' ; NO CURSOR ADVANCE? JC CPMSG INR C ; INCR CHAR POS JMP CPMSG CPMSG$DONE: XTHL ; RESTORE HL AND RET ADR RET CPMSG$TAB: MVI A,' ' ; OVER CALL CONOUT ; PRINT TO CON: INR C ; INCREMENT CHAR COUNT MOV A,C ; GET CHAR COUNT ANI 7 ; EVERY 8 JNZ CPMSG$TAB JMP CPMSG CPMSG$CR: CALL CONOUT ; PRINT MVI C,0 ; RESET CHAR COUNT JMP CPMSG * PRINT NUMBER ON CON: NUM$PRNT: PUSH PSW ; SAVE A XRA A ; A=0 STA LDSP ; TURN ON LEADING FLAG POP PSW ; GET A MVI E,'0' ; SET FOR ZERO NUM0$PRNT: SUI 100 ; COMPUTE 100'S JC NUM1$PRNT INR E ; INCREMENT 100'S JMP NUM0$PRNT NUM1$PRNT: ADI 100 ; ADD 100'S BACK IN CALL NPRNT ; PRINT NUMBER IN E MVI E,'0' ; SET FOR ZERO NUM2$PRNT: SUI 10 ; COMPUTE 10'S JC NUM3$PRNT INR E ; INCREMENT 10'S JMP NUM2$PRNT NUM3$PRNT: ADI 10 ; GET 1'S ADI '0' ; CONVERT TO ASCII CALL NPRNT ; PRINT NUMBER IN E MOV E,A ; VALUE IN E MVI C,2 ; TO CON: CALL ENTRY RET NPRNT: MOV D,A ; SAVE A IN D MOV A,E ; GET CHAR CPI '0' ; ZERO? JNZ NPRNT1 LDA LDSP ; LEADING ? ORA A ; SET FLAG JNZ NPRNT1 MVI E,' ' ; PRINT JMP NPRNT2 NPRNT1: MVI A,0FFH ; TURN OFF LEADING SP FLAG STA LDSP NPRNT2: PUSH D ; SAVE DE MVI C,2 ; PRINT TO CON: CALL ENTRY POP D ; GET DE MOV A,D ; RESTORE A RET * * THIS ROUTINE TOGGLES THE MULTIPLE RUN OPTION * OPTMR: LDA MFLG ; GET FLAG CMA ; FLIP IT STA MFLG INX H ; PT TO NEXT CHAR JMP OPT1 * * THIS ROUTINE TOGGLES THE FILE NAME DISPLAY * OPTFN: LDA FNFLG ; GET FLAG CMA ; FLIP IT STA FNFLG INX H ; PT TO NEXT CHAR JMP OPT1 * * THIS ROUTINE TOGGLES THE DISPLAY OF TIME IN THE HEADER * OPTT: LDA TDISP ; GET FLAG CMA ; FLIP IT STA TDISP INX H ; PT TO NEXT CHAR JMP OPT1 * * EXACT MODE OPTION * OPTEXACT: LDA EXACT ; GET FLAG CMA ; COMPLEMENT IT STA EXACT INX H ; PT TO NEXT CHAR JMP OPT1 * * PAGE NUMBER OPTION * OPTP: LDA PNFL ; GET FLAG CMA ; COMPLEMENT IT STA PNFL INX H ; PT TO NEXT CHAR JMP OPT1 * * LINE NUMBER OPTION * OPTN: LDA NCHK ; GET FLAG CMA ; COMPLEMENT IT STA NCHK INX H ; PT TO NEXT CHAR JMP OPT1 * * SET CHARS/LINE PARAMETER * OPTCH: CALL GET$NUM ; GET NUMBER OF CHARS/LINE MOV A,E ; ... IN A STA CHARS$PER$LINE ; SET FLAG JMP OPT1 ; CONTINUE * * SET PAGE PARAMETERS * OPTPAR: CALL GET$NUM ; GET NUMBER OF LINES OF TEXT MOV A,E ; ... IN A STA LPPT MOV A,M ; 2ND ARG? CPI ',' ; COMMA=YES JNZ OPT1 ; CONTINUE PROCESSING IF NOT CALL GET$NUM ; GET NUMBER OF LINES ON PAGE MOV A,E STA LPP MOV A,M ; 3RD ARG? CPI ',' ; COMMA=YES JNZ OPT1 ; CONTINUE PROCESSING IF NO CALL GET$NUM ; GET NUMBER OF CHARS/LINE MOV A,E STA CHARS$PER$LINE JMP OPT1 ; CONTINUE PROCESSING * * SKIP TO SPECIFIED PAGE * OPTS: MVI A,1 ; TURN ON SKIP FLAG STA SKFL CALL GET$NUM ; GET NUMBER (DECIMAL) FROM INPUT LINE INTO DE * VALUE IN DE, HL PTS TO NEXT CHAR MOV A,D ; IF DE=0, DE=1 ORA E JNZ OPTSD LXI D,1 ; SET PAGE NUMBER TO 1 OPTSD: XCHG ; NUMBER IN HL SHLD SKPNUM ; SET PAGE NUMBER TO SKIP TO XCHG JMP OPT1 ; CONTINUE PROCESSING OPTIONS * * GET NUMBER PTED TO BY HL; DE=VALUE; HL PTS TO BYTE WHICH HALTED PROCESSING * GET$NUM: LXI D,0 ; SET PAGE NUMBER TO ZERO INX H ; PT TO NUMBER * EXTRACT NUMBER OF PAGES TO SKIP OPTS1: MOV A,M ; GET CHAR CPI '0' ; VALID DIGIT? RC CPI '9'+1 RNC SUI '0' ; CONVERT TO BINARY * DE=DE*10 PUSH PSW ! PUSH H MOV H,D ; HL=DE MOV L,E MVI B,9 ; 9 LOOPS OPTS2: DAD D ; HL=HL+DE DCR B JNZ OPTS2 MOV D,H ; DE=HL MOV E,L POP H ! POP PSW * DE=DE+A ADD E ; ADD LOW MOV E,A MOV A,D ; INCR HIGH IF NECESSARY ACI 0 MOV D,A * PT TO NEXT CHAR AND CONTINUE INX H JMP OPTS1 * * HEADING OPTION * OPTH: CALL BPDASH ; PUT LEADING DASHES CALL LOADBF ; LOAD HBUF FROM COMMAND LINE JMP OPT1 * * OPEN FILE * OPEN: LDA FNFLG ; GET FILE NAME FLAG ORA A ; 0=NO JZ OPEN00 ; DO TIME IF NOT * PLACE FILE NAME IN HEADER LINE CALL BPDASH ; PUT '-- ' IN BUFFER LXI H,TFCB+1 ; PT TO FILE NAME MVI B,8 ; 8 CHARS FIRST CALL FNPUT ; PUT FILE NAME MVI A,'.' ; DOT CALL BPUT ; PUT IT MVI B,3 ; FILE TYPE CALL FNPUT ; PUT FILE TYPE JMP OPEN00 ; CONTINUE WITH TIME * * PUT B-BYTES PTED TO BY HL INTO HEADING BUFFER * FNPUT: MOV A,M ; GET BYTE CALL BPUT INX H ; PT TO NEXT DCR B ; COUNT DOWN JNZ FNPUT RET * PLACE TIME IN HEADER LINE IF SUPPORTED OPEN00: LDA TDISP ; DISPLAY TIME? (0=NO) ORA A JZ OPEN01 ; NO, PROCEED LDA TIME$SPT ; GET SUPPORT FLAG ORA A ; 0=NO JZ OPEN01 ; IF NO TIME STRING, CHECK FOR FILE NAME INCL CALL BPDASH ; PUT '-- ' IN BUFFER LHLD TIME$STR ; PT TO TIME STRING TIME1: MOV A,M ; GET CHAR FROM TIME STRING ORA A ; END OF STRING? JZ OPEN01 INX H ; PT TO NEXT CALL BPUT ; COPY INTO BUFFER JMP TIME1 * * PUT '-- ' IN BUFFER * BPDASH: MVI A,' ' CALL BPUT MVI A,'-' ; PUT '-- ' CALL BPUT ; COPY INTO BUFFER MVI A,'-' CALL BPUT MVI A,' ' CALL BPUT RET * CLOSE HEADER BUFFER AND CONTINUE WITH OPEN OPEN01: CALL BCLOS ; CLOSE HEADING BUFFER LDA EXACT ; EXACT MODE? ORA A ; 0=NO JZ OPEN0 LDA LPP ; SET NUMBER OF TEXT LINES EQUAL TO NUMBER OF PHYSICAL STA LPPT XRA A ; A=0 STA NCHK ; SET NO LINE NUMBERING STA PNFL ; SET NO PAGE NUMBERING STA HBUF ; SET NO HEADING OPEN0: CALL PRINT$ID ; PRINT PROGRAM ID LXI H,TFCB+1 ; CHECK FOR ANY '?' IN FILE NAME LXI D,IFNERR ; PREP FOR INVALID FILE NAME ERROR MVI B,11 ; 11 BYTES OPEN0L: MOV A,M ; GET BYTE INX H ; PT TO NEXT CPI '?' ; '?' NOT PERMITTED JZ OPEN1ERR DCR B ; COUNT DOWN JNZ OPEN0L LXI D,TBUFF ; SET DMA ADDRESS MVI C,26 ; BDOS FCT CALL ENTRY LDA LFLG2 ; LOG IN DRIVE IF NECESSARY MOV B,A ; NUMBER IN B ANI 80H ; MSB SET? IF SO, LOGIN JZ OPEN1 MOV A,B ; GET DRIVE NUMBER ANI 7FH ; MASK OUT MSB MOV E,A ; DRIVE NUMBER IN E MVI C,14 ; LOG IN DRIVE CALL ENTRY OPEN1: LXI D,TFCB ; PT TO FCB MVI C,15 ; OPEN FILE CALL ENTRY CPI 255 ; ERROR? JNZ ADJCPL LXI D,FERR ; FILE NOT FOUND OPEN1ERR: CALL CPRINT ; PRINT ON CON: JMP EXIT * * ADJUST COUNT OF CHARS/LINE IF LINE NUMBERING USED * ADJCPL: LDA NCHK ; LINE NUMBERING? ORA A ; 0=NO JZ COMPB LDA CHARS$PER$LINE ; ADJUST CONSTANT SUI 6 ; 6 CHARS IN LINE NUMBER STA CHARS$PER$LINE * * COMPUTE BUFFER SIZE * COMPB: PUSH H ; SAVE HL CALL SP$END MOV B,H ; PT TO BUFFER POP H LDA ENTRY+2 ; GET ADR OF FBASE SUB B ; COMPUTE NUMBER OF BLOCKS IN FBUF SUI 2 ; ADJUST COUNT OF BLOCKS STA BCNT ; SAVE BLOCK COUNT * * INITIALIZE PTRS FOR LOAD * CALL SP$END ; GET ADDRESS OF FBUF MOV D,H ; INIT PTR TO FIRST LINE IN FILE MOV E,L SHLD FPTR * * INIT PAGE OUTPUT * LDA MFLG ; CHECK FOR MULTIPLE RUNS ORA A ; 0=NO, SO ASK FOR TOF JNZ MRSKIP ; SKIP TOF PROMPT IF MULTIPLE RUNS ON PUSH H ; SAVE REGS PUSH D PUSH B LXI D,PRMS ; SET TOF CALL CPRINT ; PRINT ON CON: MVI C,1 ; READ CHAR CALL ENTRY CPI INTC1 ; ABORT? JZ EXIT CPI INTC2 ; ABORT? JZ EXIT MVI E,CR ; MVI C,2 ; WRITE CHAR CALL ENTRY MVI E,LF ; MVI C,2 CALL ENTRY POP B ; RESTORE REGS POP D POP H * * * BEGIN OUTPUT -- OPENING * MRSKIP: MVI A,CR ; INITIAL CALL COUT CALL FPAGE LDA BCNT ; GET BLOCK COUNT MOV C,A * * LOAD FILE INTO BUFFER * C=# BLOCKS TO LOAD * GETIT: CALL GETBLK ; LOAD NEXT 128 BYTES CPI CTRLZ ; EOF? JZ GETITD CALL GETBLK ; LOAD REST OF 256-BYTE BLOCK CPI CTRLZ ; EOF? JZ GETITD DCR C ; BUFFER FULL? JNZ GETIT MVI A,0 ; INDIC LOAD NOT DONE STA LDFLG JMP DISP GETITD: MVI A,1 ; INDIC LOAD DONE STA LDFLG * * DISPLAY FILE ON LST: * DISP: LHLD FPTR ; GET PTR TO NEXT LINE DISP1: LDA NCHK ; LINE NUMBERS? ORA A JZ DISP2 PUSH H ; SAVE HL LHLD LNUM ; GET LINE NUMBER INX H SHLD LNUM ; NEXT LINE NUMBER DCX H ; CURRENT LINE NUMBER CALL HLVAL ; PRINT LINE NUMBER POP H ; RESTORE LINE PTR MVI A,':' ; COLON AFTER LINE NUMBER CALL COUT DISP2: CALL PRINT ; PRINT THE LINE MOV A,M ; GET CHAR CPI CTRLZ ; EOF? JZ EXITP CALL CINT ; CHECK FOR INTERRUPT LDA BCNT ; LAST BLOCK? PUSH H ; SAVE HL CALL SP$END ; GET END ADDRESS IN HL ADD H SUI 1 ; 1 BELOW POP H ; RESTORE HL CMP H ; END OF BUFFER? JNZ DISP1 * * MOVE LAST BLOCK FROM THE LAST LOAD DOWN TO THE FRONT OF FBUF * MOVBUF: MOV C,L ; SAVE LOW MVI L,0 XCHG ; SAVE HL IN DE CALL SP$END ; GET START OF FBUF XCHG ; ... IN DE MVI B,0 ; 256 BYTES MOVB1: MOV A,M ; MOVE BYTE STAX D INX H ; INCR PTRS INX D DCR B JNZ MOVB1 * * SET UP NEW CURRENT LINE POINTER * MOV L,C ; MAKE HL PT TO NEW LOC MOV H,D DCR H SHLD FPTR ; SAVE PTR TO NEXT LINE LDA BCNT ; GET BUFFER SIZE MOV C,A DCR C ; ADJUST FOR NEW LOAD LDA LDFLG ; GET FLAG FROM LAST LOAD ORA A ; 0 MEANS INCOMPLETE JNZ DISP ; IF COMPLETE, JUST CONTINUE JMP GETIT * * LOADBF -- LOAD APPROPRIATE BUFFER WITH STRING * LOADBF: INX H ; PT TO DELIMITER MOV B,M ; GET DELIMITER INX H ; PT TO FIRST CHAR LOADB1: MOV A,M ; GET CHAR CMP B ; ENDING DELIMITER? JZ LOADB2 ORA A ; EOLN? JZ LOADB3 CALL BPUT ; PUT INTO BUFFER INX H ; PT TO NEXT CHAR JMP LOADB1 LOADB2: INX H ; PT TO NEXT CHAR LOADB3: RET * * PRINT PROGRAM ID * PRINT$ID: LXI D,PRID ; GET PROGRAM ID CALL CPRINT LXI H,TFCB+1 ; PRINT FILE NAME MVI B,8 ; 8 CHARS CALL PRFN MVI A,'.' ; DOT CALL CONOUT MVI B,3 ; PRINT FILE TYPE -- 3 CHARS CALL PRFN CALL PRINT$MESSAGE DB CR,LF,0 RET * * PRINT -- PRINT LINE PTED TO BY HL; WHEN DONE, HL PTS TO BEGINNING OF * NEXT LINE OR EOF IF ENCOUNTERED * PRINT: MVI C,0 ; INIT CHAR COUNT PRIN1: MOV A,M ; GET CHAR CPI CTRLI ; TAB? JZ PRTAB CPI CTRLZ ; EOF? JZ PREXIT CPI CR ; ? JZ PRCR CPI LF ; ? JZ PRDONE CPI BS ; ? JZ PRBS ORA A ; DONE? RZ CALL COUT ; PRINT CHAR INR C ; INCR CHAR POS PTR LDA PCC$FLAG ; PRINT CONTROL CHAR? ORA A ; 0=NO JNZ PRIN2 DB MVIA ; INSERT MVI A,X INSTR PRIN2: INR C ; INCREMENT CHAR COUNT FOR 2ND CHAR CALL EOL$TEST ; TEST AND PROCESS IF AT EOL INX H ; PT TO NEXT JMP PRIN1 * * TEST FOR EOL AND PROCESS IF SO * EOL$TEST: LDA CHARS$PER$LINE ; GET NUMBER OF CHARS/LINE SUI 3 ; ADJUST FOR EOL RC ; NO TEST IF LESS THAN 3 CHARS/LINE CMP C ; COMPARE AGAINST CURRENT POSITION JZ EOL$TEST1 JC EOL$TEST1 RET EOL$TEST1: PUSH H ; SAVE HL INX H ; ANY OF NEXT THREE CHARS A ? MOV A,M CPI CR JZ EOL$TEST2 INX H ; 2ND CHAR MOV A,M CPI CR JZ EOL$TEST2 INX H ; 3RD CHAR MOV A,M CPI CR JZ EOL$TEST2 EOL$ENDING: MVI A,' ' ; OUTPUT EOL CHARS CALL COUT MVI A,'<' CALL COUT MVI C,0 ; RESET CHAR COUNT CALL CRLF ; NEW LINE EOL$TEST2: POP H ; RESTORE HL RET * * PRINT ON PRINTER * PRBS: MOV A,C ; CHECK FOR BOL ORA A ; 0=BOL JNZ PRBS1 INX H ; PT TO NEXT -- DON'T JMP PRIN1 PRBS1: CALL COUT ; PRINT DCR C ; DECREMENT COUNT INX H ; PT TO NEXT CHAR JMP PRIN1 ; CONTINUE * * TAB TO NEXT TAB STOP * PRTAB: INX H ; PT TO NEXT CHAR PRTAB1: MVI A,' ' ; PRINT CALL COUT INR C ; TAB POS? CALL EOL$TAB$TEST ; CHECK FOR EOL MOV A,C ANI 7 ; LOW 3 BITS ORA A ; EVERY 8 (CHECK IF ZERO) JNZ PRTAB1 JMP PRIN1 ; CONTINUE W/NEXT CHAR * * TEST FOR EOL WITH TAB * EOL$TAB$TEST: LDA CHARS$PER$LINE ; CHECK TO SEE IF 3 CHARS LEFT IN LINE SUI 3 CMP C JC EOL$TT0 ; PROCESS SPECIAL TEST OF 3 OR LESS LEFT JZ EOL$TT0 RET EOL$TT0: PUSH H ; SAVE HL MOV A,C ; GET CHAR COUNT ANI 7 ; MASK FOR 8 COUNT MOV D,A MVI A,8 ; SUB FROM 8 SUB D CPI 3 ; 3 CHARS LEFT? JNC EOL$ENDING MOV D,A ; COUNT IN B EOL$TT1: INX H ; PT TO NEXT MOV A,M ; GET IT CPI CTRLI ; AUTOMATIC OVERFLOW IF ANOTHER TAB JZ EOL$ENDING CPI CR ; EOL? JZ EOL$TT2 DCR D ; COUNT DOWN JNZ EOL$TT1 JMP EOL$ENDING EOL$TT2: POP H RET * * OUTPUT AND RESET LINE COUNT * PRCR: CALL COUT ; OUTPUT MVI C,0 ; RESET LINE COUNT INX H ; PT TO NEXT CHAR JMP PRIN1 * * DONE W/PRINT * PRDONE: INX H ; PT TO FIRST OF NEXT LINE CALL CRLF$TEST ; OUTPUT AND TEST FOR PAGE EJECT RET PREXIT: LDA EXACT ; EXACT MODE? ORA A ; 0=NO RNZ CALL CRLF ; NEW LINE (PAGE PERHAPS) RET * * * CRLF -- OUTPUT TO PRINTER; DECR LINE COUNT AND PAGE IF NECESSARY * CRLF: MVI A,CR ; CALL COUT CRLF$TEST: MVI A,LF ; CALL COUT LDA LCNT ; DECR LINE/PAGE COUNT DCR A STA LCNT ; NEW COUNT RNZ CALL SKIPP ; SKIP OUT REST OF PAGE JMP FPAGE ; PRINT NEW PAGE HEADING * * SKIP OUT REST OF PAGE * SKIPP: LDA LPPT ; COMPUTE NUMBER OF LINES LEFT ON PAGE MOV B,A LDA LPP ; NUMBER OF PHYSICAL LINES SUB B ; - NUMBER OF TEXT LINES MOV B,A ; = NUMBER OF LINES LEFT ON PAGE ORA A ; DO NOTHING IF NONE LEFT RZ ; PRINT PAGE HEADING MVI A,CR ; CALL COUT MVI A,LF ; CRLF1: CALL COUT DCR B JNZ CRLF1 RET * * COUT -- OUTPUT CHAR IN A TO PRINTER * COUT: PUSH B ; SAVE REGS PUSH D PUSH H PUSH PSW XRA A ; CLEAR PRINT CONTROL CHAR FLAG STA PCC$FLAG LDA SKFL ; SKIP? ORA A ; 0=NO JNZ COUT2 POP PSW ; GET CHAR PUSH PSW ; SAVE IT AGAIN ANI 7FH ; MASK OFF MSB JZ COUT0 ; PRINT CPI FF ; FORM FEED? JZ FORM CPI CR ; ? JZ COUT0 CPI LF ; ? JZ COUT0 CPI BS ; ? JZ COUT0 CPI SPACE ; ? JNC COUT0 ; CONTROL CHAR IF LESS THAN PUSH PSW ; SAVE CHAR MVI A,'^' ; PRINT UP ARROW CALL LSTOUT ; SEND CHAR TO LST: MVI A,0FFH ; SET PRINT CONTROL CHAR FLAG STA PCC$FLAG POP PSW ; GET CHAR ADI 'A'-1 ; CONVERT FROM CONTROL TO LETTER COUT0: CALL LSTOUT ; SEND CHAR TO LST: COUT1: POP PSW ; RESTORE REGS POP H POP D POP B RET COUT2: POP PSW ; GET CHAR PUSH PSW CPI FF ; FORM FEED? JNZ COUT1 CALL SKIPP ; SKIP OUT PAGE CALL FPAGE ; SKIP NEW PAGE HEADING JMP COUT1 * * FORM FORM FEEDS THE OUTPUT * FORM: MVI A,CR ; CALL LSTOUT ; TO LST: LDA FFLG ; CHECK FOR FORM FEED ORA A ; 0=NO JZ FORM1 * FORM FEED BY ISSUING FORM FEED CHAR MVI A,FF ; CALL LSTOUT JMP FORM2 * FORM FEED BY SPACING DOWN FORM1: MVI A,LF ; LINE FEED CALL LSTOUT ; TO LST: LDA LCNT ; GET NUMBER OF LINES LEFT ON PAGE DCR A ; COUNT DOWN STA LCNT JNZ FORM1 FORM2: CALL SKIPP ; SKIP OUT AND PAGE HEAD CALL FPAGE ; NEW PAGE HEADING JMP COUT1 * * LSTOUT -- SEND CHAR IN A TO LST: * LSTOUT: MOV E,A ; CHAR INTO E MVI C,5 ; OUTPUT TO LST: CALL ENTRY RET * * CINT -- CHECK FOR INTERRUPT FROM CONSOLE * CINT: PUSH B ; SAVE REGS PUSH D PUSH H MVI C,11 ; INT? CALL ENTRY ANI 1 ; CHAR READY? JZ CINT1 MVI C,1 ; READ CHAR CALL ENTRY CPI INTC1 ; ABORT? JZ CINT0 CPI INTC2 ; ABORT? JNZ CINT1 CINT0: CALL PRINT$MESSAGE DB CR,LF,'PRINT Aborted',0 JMP EXIT CINT1: POP H ; RESTORE REGS POP D POP B RET * * CONOUT -- PRINT CHAR IN A ON CONSOLE * CONOUT: PUSH PSW PUSH B PUSH D PUSH H MOV E,A ; CHAR IN E MVI C,2 ; OUTPUT CALL ENTRY POP H POP D POP B POP PSW RET * * GETBLK -- GET NEXT TWO RECORDS; ABORT IF EOF ENCOUNTERED; * PLACE RECORDS IN MEMORY PTED TO BY DE; RET W/EOF IN A IF ENCOUNTERED * GETBLK: CALL GETSEC ; GET NEXT RECORD LXI H,TBUFF ; LOAD NEXT RECORD INTO FILE BUFFER MVI B,80H ; 128 BYTES GETBL1: MOV A,M ; GET BYTE ANI 7FH ; MASK HIGH BIT JNZ GETBL2 ; REPLACE W/@ MVI A,'@' ; @ SYMBOL GETBL2: STAX D ; STORE BYTE CPI CTRLZ ; EOF? RZ INX H ; PT TO NEXT INX D DCR B JNZ GETBL1 RET * * GETSEC -- GET NEXT RECORD FROM DISK * GETSEC: PUSH H ! PUSH D ! PUSH B LXI D,TFCB ; PT TO FCB MVI C,20 ; READ NEXT REC CALL ENTRY POP B ! POP D ! POP H ORA A ; OK? RZ LXI D,RERR ; READ ERROR CALL CPRINT ; PRINT ON CON: JMP EXIT * * EXIT -- EXIT PRINT PROGRAM; LOG IN ORIGINAL DRIVE IF NECESSARY * * EJECT FINAL PAGE EXITP: LDA FFLG ; FORM FEED? ORA A ; 0=NO JNZ EXITP2 LDA LCNT ; GET NUMBER OF LINES LEFT ON PAGE MOV B,A ORA A ; NO LINES LEFT? JZ EXITP1A MVI A,CR ; CALL COUT MVI A,LF ; * FORM FEED BY SPACING DOWN EXITP1: CALL COUT ; OFF PAGE DCR B JNZ EXITP1 EXITP1A: CALL SKIPP ; SKIP OUT REST OF PAGE JMP EXIT * FORM FEED BY SENDING CTRL-L EXITP2: MVI A,FF ; CALL COUT * LOGIN ORIGINAL DISK IF NECESSARY AND RETURN TO CP/M EXIT: LDA LFLG ; GET LOGIN FLAG CPI 0FFH ; NO LOGIN NECESSARY? JZ EXIT1 MOV E,A ; DRIVE NUMBER MVI C,14 ; LOG IN DRIVE CALL ENTRY EXIT1: JMP 0 ; RET TO CP/M * * FPAGE -- PRINT HEADING ON PAGE * FPAGE: PUSH H ; SAVE REGS PUSH D PUSH B LDA SKFL ; SKIPPING? ORA A ; 0=NO JZ PAGEN LHLD PNUM ; CHECK ON CURRENT PAGE NUMBER XCHG LHLD SKPNUM ; STOP SKIPPING? MOV A,H CMP D ; D=H? JNZ PAGEN MOV A,L CMP E ; DE=HL? JNZ PAGEN MVI A,0 ; STOP SKIPPING STA SKFL * * PRINT PAGE NUMBER * PAGEN: LDA PNFL ; NUMBER PAGES? ORA A ; 0=NO JZ PAGEN3 * PRINT 'Page nnnnn' LXI H,PAGMS ; 'PAGE' PAGEN1: MOV A,M ; GET CHAR ORA A ; DONE? JZ PAGEN2 CALL COUT ; PRINT IT INX H ; PT TO NEXT JMP PAGEN1 PAGEN2: XRA A ; SET LEADING BLANK FLAG STA LBFLG LHLD PNUM ; GET PAGE NUMBER INX H ; INCR PAGE NUMBER SHLD PNUM ; NEXT PAGE NUMBER DCX H ; CURRENT PAGE NUMBER CALL HLVAL ; PRINT HL * PRINT HEADER LINE IF ANYTHING IN IT PAGEN3: LXI H,HBUF ; PT TO BUFFER MOV A,M ; SOMETHING TO PRINT? ORA A JZ PAGEN4 CALL PRINT ; PRINT STRING PTED TO BY HL * SET PAGING PARAMETERS PAGEN4: LDA LPPT ; SET LINES/PAGE OF TEXT COUNT STA LCNT LDA EXACT ; EXACT MODE? ORA A ; 0=NO JNZ PAGEN5 CALL CRLF ; 2 LINES IF NOT EXACT MODE CALL CRLF PAGEN5: POP B POP D POP H RET * * PRINT HL AS FIVE DEC DIGITS W/LEADING BLANKS * HLVAL: XRA A ; SET LEADING BLANK FLAG STA LBFLG LXI D,10000 ; 10,000'S CALL DISPN ; DISPLAY DIGIT LXI D,1000 ; 1000'S CALL DISPN LXI D,100 ; 100'S CALL DISPN LXI D,10 ; 10'S CALL DISPN MOV A,L ; 1'S ADI '0' CALL COUT RET * * DISPLAY 10'S DIGIT COUNTS * DISPN: MVI C,0 ; INIT COUNT DISPN1: INR C ; INCR CNT MOV A,L ; HL=HL-DE SUB E MOV L,A MOV A,H SBB D MOV H,A JNC DISPN1 ; CONT UNTIL NEG DCR C ; ADJUST CNT MOV A,L ; HL=HL+DE ADD E MOV L,A MOV A,H ADC D MOV H,A LDA LBFLG ; LEADING BLANK? ORA C JZ DISPN2 STA LBFLG ; NO MORE BLANKS MOV A,C ; DISPLAY COUNT ADI '0' CALL COUT RET DISPN2: MVI A,' ' ; LEADING CALL COUT RET * * PBUF -- PRINT CONTENTS OF BUFFER; 1ST BYTE=1 IF ANYTHING THERE; STRING * ENDS IN 0 * PBUF: MOV A,M ; GET 1ST BYTE INX H ; PT TO 1ST CHAR TO PRINT ORA A ; ANYTHING THERE? CNZ PRINT ; PRINT LINE RET * * BUFFER I/O ROUTINES * BOPEN -- OPEN BUFFER PTED TO BY HL; A=SIZE OF BUFFER * BPUT -- PUT CHAR IN A INTO BUFFER; RET W/ZERO SET IF BUFFER FULL * BCLOS -- CLOSE BUFFER * BOPEN: SHLD BPTR ; SET BUFFER PTR STA BSIZE ; SET BUFFER SIZE RET BCLOS: PUSH H ; SAVE HL LHLD BPTR ; GET PTR MVI M,0 ; STORE ZERO POP H RET BPUT: PUSH H ; SAVE HL, BC PUSH B MOV B,A ; SAVE A IN B LDA BSIZE ; CHECK BUFFER SIZE ORA A ; 0=FULL JZ BPUTF DCR A ; DECREMENT SIZE STA BSIZE ; NEW BUFFER SIZE LHLD BPTR ; GET PTR MOV M,B ; STORE CHAR INX H ; PT TO NEXT SHLD BPTR ; SET PTR BPUTF: POP B ; GET BC, HL POP H ORA A ; SET ZERO FLAG (BUFFER SIZE) IF FULL RET * * OPTION COMMAND TABLE * CMD$TABLE: DB 'C' ; CONFIGURATION DW OPTCONFIG DB 'E' ; EXACT MODE DW OPTEXACT DB 'F' ; FILE NAME DISPLAY DW OPTFN DB 'H' ; HEADING DW OPTH DB 'L' ; LINE NUMBERS DW OPTN DB 'M' ; MULTIPLE RUNS DW OPTMR DB 'N' ; PAGE NUMBERS DW OPTP DB 'P' ; PAGE PARAMETER SETTING DW OPTPAR DB 'S' ; SKIP TO SPECIFIED PAGE DW OPTS DB 'T' ; TIME DISPLAY DW OPTT DB 'W' ; SET WIDTH (CHARS/LINE) DW OPTCH DB 0 ; END OF TABLE * * CONFIGURATION COMMAND TABLE * CONFIG$CMD: DB CTRLC ; ABORT DW EXIT DB 'C' ; CHAR COUNT DW CF$CHAR DB 'E' ; EXACT MODE TOGGLE DW CF$EXACT DB 'F' ; FORM FEED TOGGLE DW CF$FORM DB 'G' ; FILE NAME TOGGLE DW CF$FNF DB 'L' ; LINE NUMBER TOGGLE DW CF$LINE DB 'M' ; MULTIPLE RUNS DW CF$MRF DB 'N' ; TEXT/PHYSICAL LINE COUNTS DW CF$NUM DB 'P' ; PAGE NUMBER TOGGLE DW CF$PAGE DB 'T' ; TIME TOGGLE DW CF$TIME DB 'X' ; EXIT AND UPDATE DW OPTWR DB 'Y' ; CHANGE FILE NAME DW CF$FNAME DB 0 ; END OF TABLE * * MESSAGE SECTION * PRID: DB 'PRINT II, Version ' DB VERS/10+'0','.',(VERS MOD 10)+'0',' -- File Name: $' PRMS: DB ' Please set Top of Form',CR,LF DB ' Type CTRL-C or to Abort, Anything Else to ' DB 'Continue -- $' OPTER: DB CR,LF DB ' PRINT x:filename.typ /o',CR,LF DB ' Only ''filename.typ'' is required.',CR,LF DB 'PRINT Options may be combined; ' DB 'Valid PRINT Options are --',CR,LF DB ' /C = Enter PRINT II Configuration Mode',CR,LF DB ' /E = Exact Print [Expand Tabs, Form Feed, No ' DB 'Line or Page Numbers]',CR,LF DB ' /F = TOGGLE File Name Display on Page Header',CR,LF DB ' /H heading text = Heading',CR,LF DB ' /L = TOGGLE Numbering of Each Line',CR,LF DB ' /M = TOGGLE Multiple Runs (MR = No TOF Msg)',CR,LF DB ' /N = TOGGLE Numbering of Each Page',CR,LF DB ' /Pn1,n2,n3 = Set Page Parameters',CR,LF DB ' n1 = Number of lines of text on page',CR,LF DB ' n2 = Number of physical lines on page ' DB '(",n2" is optional)',CR,LF DB ' n3 = Number of characters per line ' DB '(",n3" is optional)',CR,LF DB ' /Sn = Skip to Specified Page',CR,LF DB ' /T = TOGGLE Time Display in Header',CR,LF DB ' /Wn = Set Width of Line (Chars/Line) to n',CR,LF DB CR,LF,' Examples of options are --',CR,LF DB ' /H/text/ /H''text of header'' /S24 /N /P56,66,80',CR,LF DB '$' CMDERR: DB 'Invalid Command',CR,LF,'$' FERR: DB CR,LF,'File not Found$' IFNERR: DB CR,LF,'Invalid File Name -- Contains "?" or "*"$' RERR: DB CR,LF,'Disk Read ERROR$' PAGMS: DB ' Page ',0 DS 100 ; STACK SPACE STACK: DS 2 ; TOP OF STACK * * BUFFER REGION * TIME$SPT: DS 1 ; TIME SUPPORT FLAG (0=NO) TIME$STR: DS 2 ; PTR TO TIME STRING BPTR: DS 2 ; POINTER TO NEXT CHAR IN BUFFER BSIZE: DS 1 ; NUMBER OF BYTES LEFT IN BUFFER SAVE$FLAG: DS 1 ; SAVE CHANGE FLAG BCNT: DS 1 ; BUFFER BLOCK COUNT PCC$FLAG: DS 1 ; 0=DIDN'T PRINT CONTROL CHAR, 0FFH=DID LFLG: DS 1 ; LOGIN FLAG (ALT DRIVE LOGGED IN) LFLG2: DS 1 ; NUMBER OF ALT DRIVE (MSB SET IF SO) LDFLG: DS 1 ; LOAD FLAG (LOAD INCOMPLETE) LDSP: DS 1 ; LEADING SPACE FLAG FPTR: DS 2 ; PTR TO NEXT LINE IN FBUF PNUM: DS 2 ; PAGE NUMBER BUFFER SKFL: DS 1 ; SKIP FLAG; 0=NO SKPNUM: DS 2 ; PAGE NUM TO SKIP TO LCNT: DS 1 ; LINE COUNT BUFFER LBFLG: DS 1 ; LEADING BLANK FLAG (0=YES) EOL$FLAG: DS 1 ; EOL FLAG LNUM: DS 2 ; LINE NUMBER VALUE INPBUF: DB 20 ; UP TO 20 CHARS DS 21 ; CHARS PLUS CHAR COUNT * * SUPPORT PACKAGE ROUTINES * ORG $/256*256+256 ; BEGINNING OF SUPPORT PACKAGE JMP SP$END ; JUMP TO END ADDRESS ROUTINE JMP SP$TIME ; JUMP TO TIME FUNCTION ROUTINE SP$END: LXI H,SUPEND ; END ADDRESS/BEGINNING OF FBUF RET SP$TIME: NOP ; NOP FOR 3 BYTES XRA A ; 0 MEANS NO TIME RETURNED RET SUPEND EQU $/256*256+256 ; ENDING OF SUPPORT PACKAGE END