Listing of file='SPOOLR.SRC;01' on disk='vmedia/chip_138-sector.ccvf'
; PRINTER SPOOLER PROGRAM ; BY TOM DEVLIN ; 115 EASTVIEW AVE ; LAKE ORION, MI. 48035 ;LAST REVISED 5/29/86 ; This program will print .SRC (ASCII) files while another ;program is running provided that the other program; ; (A) respects the BASIC top of memory pointer, ; (B) doesn't use RS232 output, (this includes SOUNDWARE) ; (C) doesn't use the user timer. ;(NOTE: If you intend to run a BASIC program BASIC must be ;initalized prior to running the spooler program. This is ;because an [ESC]-[W]-[RETURN] will overwrite the disk buffer ;and a <CPU RESET> will kill the spooler.) ; Both programs will run without interaction except that disk ;access by one program will temporarily pause the other one, ;this may cause you to lose key-strokes if you are typing ;when the spooler reads more data from the file. You can ;decrease the number and frequency of the disk accesses by ;increasing the BUFBLK value, this lowers the programs' ORG ;point and increases the size of the disk buffer in 128 byte ;increments. As written the program used a BUFBLK value of 8, ;this gives a 1K disk buffer and the program runs in just ;under 2K total starting at 0F800H. (0B800H for 16K machines) ; ; Once printing has started you must not remove the disk ;containing the file being printed nor overwrite the file, ;anything else is OK. ; ; You can re-start the program via [ESC]-[^] provided that ;it hasn't been over-written since it was last run. (It ;un-protects itself on exit.) ; ; The program filters out Form Feeds and replaces them with ;line feed / carrage return pairs. ; ; This program is based on the old Colorcue printer driver ;program as included on the MLDP disk. It has been EXTENSIVLY ;revised and is, I believe, now bug-free. ; USER CUSTOMIZING AREA ;PRINTER INFO (MX-80 TYPICAL), CHANGE ONLY IF NECESSARY PW EQU 80 ;MAX CHARS/LINE OF PRINTER PL EQU 66 ;MAX LINES/PAGE OF PRINTER PRATE EQU 0 ;PRINTER BAUD RATE ; USE YOUR PRINTERS' BAUD RATE (1-7) ; AND THE SPOOLER WILL SET THE CC-II ; RS-232 PORT FOR YOU. IF PRATE EQU 0 ; THE BAUD RATE WILL NOT BE CHANGED. ;PAGE FORMATTING VALUES, CHANGE AS DESIRED LM EQU 4 ;LEFT MARGIN RM EQU 4 ;RIGHT MARGIN TM EQU 2 ;TOP MARGIN BM EQU 3 ;BOTTOM MARGIN TOPRAM EQU 0FFFFH ;32K TOP OF MEMORY, FOR 16K USE 0BFFFH BUFBLK EQU 8 ;NUMBER OF 128 BYTE DISK BUFFER BLOCKS ; END OF CUSTOMIZING AREA, BEYOND THIS POINT BE DRAGONS. ; SYSTEM EQUATES BAUD EQU 5 ;TMS-5501 BAUD RATE PORT LO EQU 0033H ;CHAR OUTPUT ROUTINE BEGEX EQU 0038H ;JUMPS TO BEGIN ESCCRT EQU 81BFH ;ESCAPE ^ JUMP VECTOR RST1J EQU 81C8H ;USER TIMER INTERUPT VECTOR EXTBF EQU 81D6H ;HOLDS TMS-5501 OUTPUT STATUS INPCRT EQU 81C5H ;JUMP VECTOR NUMBER 31 KBDFL EQU 81DFH ;HAS NUMBER OF KBD JUMP VECTOR CRATE EQU 81E2H ;HOLDS CURRENT BAUD RATE INPFL EQU 81E3H ;SERIAL INPUT FLAG STORAGE OUTFL EQU 81F8H ;OUTPUT PORT FLAG READY EQU 81FFH ;KEYBOARD STATUS KBCHA EQU 81FEH ;KEYBOARD CHAR MAXRAM EQU 32940 ;BASIC TOP OF MEMORY POINTER ; CONTROL CHARACTERS USED BY THIS PROGRAM BELL EQU 7 ;BELL TAB EQU 9 ;TAB LF EQU 10 ;LINE FEED FF EQU 12 ;FORM FEED CR EQU 13 ;CARRAGE RETURN R EQU 17 ;RED G EQU 18 ;GREEN Y EQU 19 ;YELLOW B EQU 20 ;BLUE M EQU 21 ;MAGENTA C EQU 22 ;CYAN W EQU 23 ;WHITE ; ASSORTED OTHER VALUES CL EQU PW-LM-RM ;# PRINTABLE CHARACTER POSITIONS/LINE BUFSIZ EQU BUFBLK*128 ;DISK BUFFER SIZE PRGLEN EQU 03FFH ;LENGTH OF RUNNING CODE + A LITTLE RATE EQU ((128 SHL PRATE) SHR 8) OR ((126+PRATE) AND 128) ;BAUD RATE BYTE (TRICKY, HUH?) ORG TOPRAM-PRGLEN-BUFSIZ ; START ADDRESS OF PROGRAM START: CALL SETUP ;OVERLAY JUMP TABLE IF V6.78 MVI A,12 ;KEYBOARD STA KBDFL ; TO BIT BUCKET STA INPFL ;SERIAL PORT AS WELL LXI H,MSG00 ;PRINT CALL OSTR ; STARTUP MESSAGE FILES: CALL INBUFF ;GET FILE NAME CALL INIIO ;SET THINGS UP CALL EMESS ;IN CASE ERROR JNZ FILES ;RETRY IF ERROR LXI H,HLTMSG ;TELL HOW CALL OSTR ; TO PAUSE PROGRAM XRA A ;ZERO A LXI H,MARCNT ;POINT TO MARGIN COUNTER MOV M,A ; CLEAR IT INX H ;POINT TO PAGE COUNTER MOV M,A ; CLEAR IT INX H ;POINT TO CHAR COUNTER MOV M,A ; CLEAR IT INX H ;POINT TO LINE COUNTER MOV M,A ; CLEAR IT INX H ;POINT TO OURFLG MOV M,A ; START AT INT0: STA OUTFL ;TO TURN OFF ANY XMIT INTERUPTS ORI RATE ;GET BAUD RATE JZ NORATE ; IF ZERO DON'T CHANGE EXISTING OUT BAUD ;SET BAUD RATE PORT STA CRATE ; UPDATE CURRENT RATE BYTE NORATE: LHLD MAXRAM ;GET BASIC TOP OF MEMORY SHLD TEMPTOP ; SAVE IT LXI H,START-1 ;PROTECT SHLD MAXRAM ; THIS PROGRAM LXI H,START-51 ;INITALIZE BASICS' SHLD 80D2H ; STACK POINTER CALL STARTUP ;START USER TIMER BAILOUT: LXI SP,8042H ;FCS STACK LXI H,KBDFL ;KEYBOARD FLAG LXI D,BEGEX ;DO NOTHING PUSH D ; LOOP ADDRESS JMP ESCD ;GO TO FCS STARTUP: MVI A,0C3H ;SET USER TIMER STA RST1J ; VECTOR LXI H,ENTRY ; TO OUR SHLD RST1J+1 ; ROUTINE MVI A,0FFH ;START THEM INTERUPTS OUT 10 ; A-GOIN OFF RET ; THIS IS THE RST1J VECTOR, WE COME IN HERE WHEN THE USER ;TIMER GOES OFF AND THEN BRANCH TO THE ACTIVE ROUTINE. ENTRY: PUSH PSW ;SAVE AF AND PUSH H ; HL ON USER STACK LXI H,0 ;CLEAR HL DAD SP ;ADD USER STACK POINTER LXI SP,STACK ;SWITCH TO OUR STACK PUSH H ;SAVE USER STACK POINTER PUSH D ; SAVE DE PUSH B ; AND BC LXI H,EXIT ;SET EXIT AS THE PUSH H ; PLACE TO RETURN TO LXI H,OURFLG ;POINTER TO NEXT ROUTINE PUSH H ;SAVE A COPY MOV A,M ;GET ROUTINE POINTER LXI H,TABLE ;GET TABLE BASE ADDRESS CALL ADHLA ;INDEX UP TABLE MOV A,M ;LO BYTE OF ROUTINE INX H ;POINT TO MOV H,M ; HIGH BYTE MOV L,A ;ADDRESS COMPLETE XTHL ;SWAP TO TOP OF STACK RET ; AND GO TO THE ROUTINE EXIT: MVI A,020H ;DELAY UNTIL USER TIMER OUT 10 ; SENDS US TO ENTRY: AGAIN POP B ;RESTORE BC POP D ; AND DE POP H ;GET USER STACK POINTER SPHL ; GO BACK TO USER STACK POP H ;RESTORE HL POP PSW ; AND AF EI ;ENABLE INTERUPTS RET ;AND RETURN TO USER INT0: ;WE VECTOR HERE TO GET THE NEXT CHARACTER WHEN OURFLG=0 LXI H,MARCNT ;POINT AT MARGIN COUNTER INR M ;BUMP COUNT MVI A,LM ;GET MARGIN LENGTH CMP M ;THERE YET? MVI A,' ' ;GET A SPACE TO SEND JNC S1OUT ; IF MARGIN NOT COMPLETE INX H ;POINT AT PAGE NUMBER MOV E,M ; SAVE IT INX H ;POINT TO CHAR COUNTER MVI A,CL ;MAX CHARS/LINE CMP M ; SEE IF NEW LINE NEEDED JZ LFEED ;YES, DO CR/LF INX H ;POINT TO LCOUNT MOV A,E ;GET PAGE NUMBER BACK ORA A ; IS IT PAGE ZERO? JZ PAGE0 ; YES, SO NO TOF LINE FEEDS MOV A,M ;GET CURRENT LINE # INR A ;SEE IF NEXT LINE CPI TM+1 ; IS WITHIN TOP MARGIN JC LFEED ; SEND CR/LF IF LINE <= TM PAGE0: MOV A,M ;LINE # BACK XRI PL-BM ;LAST LINE ON PAGE? JNZ GETNXT ;NO, GET NEXT BYTE MOV M,A ;CLEAR LINE COUNT DCX H ;POINT TO DCX H ; PAGENO INR M ;COUNT NEW PAGE DCX H ;POINT TO MARCNT MOV M,A ; CLEAR IT MVI A,FF ;DO A JMP S1OUT ; FORM FEED GETNXT: CALL GETBYTE ;READ NEXT BYTE FROM FILE CPI FF ;FORM FEED? JZ LFEED ;YES, REPLACE WITH CR/LF CPI TAB ;TAB? JNZ S1OUT ; NO, PRINT IT LXI H,OURFLG ;POINT TO MVI M,2 ; INT2: INT2: ;WE VECTOR HERE WHILE REPLACING TAB WITH SPACES MVI E,' ' ;SPACE LDA CCOUNT ;TEST CURRENT COLUMN INR A ; NUMBER FOR ANI 7 ; EVEN MULTIPLE OF 8 JNZ S1OUT+1 ;>1 SPACE NEEDED MOV M,A ;BACK TO MAIN ROUTINE JMP S1OUT+1 ;PRINT LAST SPACE GETBYTE: ; READ NEXT BYTE FROM OPEN FILE LXI H,FPB1 ; POINT AT FILE PARAMETER BLOCK CALL GTBYT ; GET NEXT BYTE RNC ; <C>=ERROR OR END OF FILE POP H ;'EXIT' FROM SUBROUTINE MVI A,6 ;TO KILL PROGRAM STA OURFLG ; AFTER 1 FINAL CHARACTER MVI A,FF ;ASSUME END OF FILE JZ S1OUT ; IF SO, SEND FORM FEED MVI A,BELL ;MUST BE DISK ERROR SO JMP S1OUT ; RING PRINTER BELL INSTEAD ; VECTOR HERE IF OURFLG=4 BECAUSE WE COULDN'T PRINT ANYTHING ; LAST CYCLE. (TBUFFER WASN'T EMPTY OR CLEAR TO SEND WAS HIGH) INT4: LXI D,TMPFLG ;POINT TO TEMP FLAG STORAGE LDAX D ;MOVE CONTENTS MOV M,A ; BACK TO OURFLG INX D ;POINT TO NXTOUT LDAX D ; GET CHARACTER TO SEND S1OUT: MOV E,A ;SAVE CHARACTER IN 03H ;TBUFFER ANI 10H ; EMPTY? JZ SVSTAT ;NO, TRY AGAIN LATER MVI A,128 ;READ OUT 7 ; KEYBOARD IN 1 ;PATTERN MOV D,A ;SAVE PATTERN LDA EXTBF ;ORIGINAL STATE OUT 7 ;RESTORE PORT MOV A,D ;GET PATTERN BACK ANI 070H ;CONTROL+SHIFT+REPEAT? JZ PAUSE ; YES! MASTER WANTS US IN 1 ;TEST CLEAR TO SEND ORA A ;SET FLAGS JP SVSTAT ;CTS WASN'T LO MOV A,E ;SEND CHAR OUT 06H ; TO TX-BUFFER LXI H,CCOUNT ;POINT AT CHAR COUNTER CPI ' ' ;CONTROL CHAR? JC NOCNT ;YES, DON'T COUNT IT INR M ;COUNT PRINTABLE CHAR NOCNT: CPI CR ;JUST SENT A CARRAGE RETURN? JNZ TRYLF ;NO, SEE IF LINE FEED MVI M,0-LM ;CLEAR CHAR COUNT TRYLF: INX H ;POINT TO LINE COUNT XRI LF ;LINE FEED? RNZ ;NO, EXIT INR M ;COUNT NEW LINE STA MARCNT ;CLEAR LEFT MARGIN COUNTER RET ; AND EXIT SVSTAT: LXI H,OURFLG ;SAVE STATE TO RETURN TO MOV A,M ;GET CURRENT FLAG MVI M,4 ; CHANGE OURFLG TO 4 INX H ;POINT TO TMPFLG MOV M,A ;SAVE OLD FLAG INX H ;POINT TO NXTOUT MOV M,E ;SAVE CHARACTER RET ;GO BACK TO USER INT6: ;FINAL EXIT FROM PRINT PROGRAM LHLD TEMPTOP ;RESTORE TOP OF SHLDMA_RAM ; MEMORY POINTER KILLIT: LXI H,0 ;ZEROR*"U55e5 ORG $-2 ;P)APAST?DUM;MY BYTES EI ; LOAD REAL RET ; HL CONTENTS SHLD RST1J ; KILL USER TIMER RET ;AND END PROGRAM ;?SEND CR/LF TO PRINTER IN TWO PASSES LFEED: MVI A,8 ;POINT TO STA OURFLG ; SEND LF ROUTINE MVI A/CR ;SEND THE JMP S1OUT ; CARRAGE RETURN INT8: MVI M,0 ;BACK TO MAIN ROUTINE MVI A,LF ;SEND THE JMP S1OUT ; LINE FEED ; IF <COMMAND>&<REPEAT> KEYS ARE PRESSED WHILE PRINTING ; WE SAVE THE STATE WE ARE MN AND SuT UP A PATCH TO INTERCEPT ; THE NEXT KEY,PRESSED. PAUSE: s}LL SVSTAT ;SO RETURO?TOSU?INW7?TO?ROUTINE INX H ;1st BYTE OF INPCRT STORAGE XCHG ; TO DE LXI H,INPCRT ;GET KEYBOARD VECTOR PUSH H ;SAVE IT MVI B,3 ;MOVE INPCRT CONTENTS CALL MOVDH ; TO STORAGE AREA LXI H,KBDFL ;SAVE MOV A,M ; KBDFL STAX D ; CONTENTS MVI M,31 ;SO WE GET THE NEXT KEY POP H ;INPCRT ADDRESS BACK MVI M,0C3H ;JMP LXI H,CAPTURE ;WHERE NEXT KEY WILL VECTOR SHLD INPCRT+1 JMP KILLIT ;HOLD FOR NEXT KEY ;NOTE THAT THIS ROUTINE IS NOT PART OF THE PROGRAM PROPER, ;IT'S A PATCH WE HOOK TO THE KEYBOARD ROUTINE THRU INPCRT ;WHEN WE WANT THE NEXT KEY PRESSED. CAPTURE: MOV L,B ;POINT TO READY MOV M,A ;SIGNAL NO KEY IN LXI H,UVEC ;USER INPCRT VECTOR STORAGE LXI D,INPCRT ;RESTORE MVI B,3 ; ORIGINAL CALL MOVDH ; INPCRT VECTOR MOV A,M ;RESTORE STA KBDFL ;USER KBDFL CONTENTS LXI H,KBCHA ;GET MOV A,M ; THE KEY MVI M,0 ;CLEAR KBCHA CPI LF ;LINE FEED? JNZ STARTUP ;NO, RESUME PRINTING JMP INT6 ;PROGRAM ABORTED ;PRINT MESSAGE AND INPUT BUFFER WITH BACKSPACE EDITING INBUFF: LXI H,MSG01 ;DISPLAY CALL OSTR ; 'PRINT>' CALL RESET ;RESET DISK IF ERROR LXI H,BUFFER ;POINT AT BUFFER L02: XRA A ;ZERO A MOV M,A ;INSERT BUFFER TERMINATOR LXI D,KBCHA ;ZERO STAX D ; KBCHA GET1: LDAX D ;WAIT ORA A ; FOR A JZ GET1 ;KEY CPI LF ; USER WANT OUT? JZ BAILOUT ; YES! EXIT PROGRAM CPI CR ;IS KEY A CARRAGE RETURN? JZ CRLF ; PRINT CR/LF AND EXIT SUB LXI B,L02 ;PUSH LO2: ONTO THE PUSH B ; STACK FOR RETURN CPI 26 ;IS KEY LEFT ARROW? JZ KILL1 ; YES, DELETE LAST CHAR CPI 07FH ;DELETE MAYBE? JNZ L03 ; NO, KEEP GOING KILL1: MOV A,L ;ARE WE AT THE CPI BUFFER AND 255 ; START OF THE LINE? RZ ;YES, SO DON'T DELETE ANYTHING DCX H ;BACK UP 1 POSITION PUSH H ;SAVE BUFFER STATE LXI H,BACKUP ;ERASE LAST CALL OSTR ; LETTER POPh ;RESTORE BUFFER POINTER RET B' 9CONTINUE LOOP AT L02: L03: CPI ' ' ;CONTROL CHARACTER? RC ; YES, IGNORE IT MOV A,L ; GET BUFFER LO BYTE CPI (BUFFER+4+6+1+3+1+2) AND255 RZ ;1 TOO MANY! LDAX D ;GET KEY AGAIN CPI 'a'-1 ;CAPS LOCK UP? JC UPPER ; NO, USE AS IS SUI 'a'-'A' ;CONVERT TO UPPER CASE UPPER: MOV M,A ;BUFGER KEY INX H ;BUMP POINTER LO ;ECHO KEY AND GO AFTER ANOTHER ; FPB?- FILE PARAMETER BLOCK LAYOUT FOPT EQU 0 FATR eQU 1 FNAMQTUBKgQeQTUBj FVERiEQU 11 fSBK EQU12 FSIZ EQU 14 FLBC EQTNU 16 FLAD EQU 17 FSAD EQU 19!%EQU 21 FDBK EQU 22 FDEN EQU 23 FaUX EQU 24 FHAN EQU 26 ffCN EQU 28 FDRV EQU 29 FBLK EQU 30 FBUF EQU 32 FXBC EQU 34 FPTR EQU 36 ; GET INFO FROM COMMAND LINE BUFFER INTO FILE PARAMETER BLOCK INIIO: LXI H,BUFFER ; POINT AT BUFFER LXI D,FPB1 ; POINT AT INPUT FPB LXI B,DEFAULT ; POINT AT DEFAULT TYPE CALL PFSPC ; PARSE FILE SPEC RC ; IF CARRY THEN ERROR XRA A ; ZERO A LXI H,FJ ; POINT AT INPUT FPB MOW M,A ; 0=OLD FILE CALL OPEN ; OPEN wHE FILE RC ; ERROR LXI H,IBUF ; POINT AT INPUT zUFFER SHLD FPB1+FBUFi;YINPUTT IUMM5 LXi H,BUFSIZ ; SETUP BUFFER SIZE SHLD F^B1+FXBC ; SAVE INPUT8zUFFER SIZE LXI H,FPr9 ; POINT AT INPUT FPB JMTRWSuQI ; REWIND INPUT FILE & RETUSN TAzLE 9 T?_OMNTS TO NE\T/SOUWMOE GW INW< ;<,%r=I51WEJ wW INT2zb7' IUQ%95 DWInT) 4 kUWAITING<FOZ> U/Je:;6,T*AEXIW U(ʊKKK SEND LINE FEEG 'jMMյHju0: DB21$11,MIrڱ{Z,LF,7\RIUŚA-Q3UOoLER ' ֱ'V1.37,R,' (FOR7,G,' /SIՊB%' FILuS?OOLY)',KR,Ik MSg05: Dr C,sZ,DF$7XRiNT>$7$w,; hDTESG: Drb,Gm UPRESS'.Y,'><{OMMANt>7,G,'0ANF) DB ' <REPU;b:' KEYS TO PAUSE PRINTING,',CR,LF DB Y,'<DOWN ARROW>',G,' THEN?KMLLSqRAM,' DB Y,' <RETURN>',G,' RESUMES<IT.',CR,LF,LG/W}C/C DB 'YOU MAY NOW RUN ANOTHER%ZqM',{R,LF,LF,239 DEFU" SRC' BACKUP: DB 26,''239 NEWTAB: ; ROM JUMP T((DEFAULT = V8.79) OS*H 182AH EMESS: JMP 0AD6H PFSPC: JMP 14ADH RESET: JMP 0B48H OXEN JMBLLQLHHu5UE5) JMP 15 GWbYT: JMBNz5 : Jm^194EH MOVJJ)5A%1871H *UN ESCf: UYJMPFFHʍSETUP: LXI D/OEWTAB ;AGDRESS?OF JUMPTABLE LXI HOLU %;ADdRESS OFzYI1e5 MVI B$LEFT}z ;NUMBuzYJYTeSX TO MOVE LDA 1 IS GCS VERSION CPI 0BAH ;rj CNZ&!% ;NO, sALL V6.78 MOVH/ʕ%A,0C3H ;JMP' STA ESCCRT ;ESEC-^ VECTOR POP H ;USE THE RETURN ADDRESS SHLD ESCCRT+1 ; FOR ANY FUTURE RE-ENTRY PCHL ; INCLUDING THIS ONE OLDTAB: ; V6.78 ADDRESSES (WILL OVERLAY JUMP TABLE IF NEEDED) JMP 33F4H JMP 262DH JMP 3077H JMP 26A5H JMP 2DArH JMP 30C6H JMP 322CH JMP 3518H JMP 343BH JMP 338BH JMP 32C9H LENTAB EQU $-OLDTAB ENDPRG: ;END OF(UU1.PRG CODE ORG SETUPK ;SAVE A LITTLE RAM SPACE ;DATA AREAS (ORDER IS IMPORTANT) TEMPTOP: DS 2 ; TEMP BASIC TOP MEMORY POINTER MARCNT: DS 1 ; LEFT MARGIN COUNTER PAGENO: DS 1 ; PAGE NUMBER CCOUNT: DS 1 ; CURRENT CHAR COUNT LCOUNT: DS 1 ; CURRENT LINE COUNT OURFLG: DS 1 ; POINTS TO CURRENT ROUTINE TMPFLG: DS 1 ; USED BY INT4 ROUTINE NXTOUT: DS 1 ; NEXT CHAR TO SEND UVEC: DS 3 ; USER INPCRT VECTOR STORAGE FLAG: DS 1 ; STORES KBDFL FPB1: DS 38 ;INPUT FPB BUFFER: DS 100 ;COMMAND LINE BUFFER STACK: ; AnD STACK AREA (ONu GO UP ;AND DA UDDER GO DOWN) IBUF: DS BUFSIZ ;DISK BUFFER DUMMY EQU ENDPRG ;JUST A REFERENCE FOR THE ; .LDA TO .PRGUIM%=95 END START