TITLE SIMPLE printer driver for WS4, CP/M ; ; Submit DRIVER.SUB to build a SIMPLE.DRV file that can be included in the ; WSPRINT.OVR file using WSCHANGE. ; IF1 .PRINTX -SIMPLE, 06 Jul 87- ELSE .PRINTX -Pass 2- ENDIF ASEG ORG 8680H ; Fixed load point for WS4 #21 ; ; Equates ; TPA EQU 100H ; Where TPA starts for WordStar ; ; Special Characters ; CR EQU 0DH ; Carriage return LF EQU 0AH ; Line feed EOF EQU 1AH ; End of file mark BS EQU 08H ; Backspace DEL EQU 7FH ; Delete ESC EQU 1BH ; Escape BESC EQU 1CH ; Back escape TAB EQU 09H ; Tab FFEED EQU 0CH ; Form feed SOFTHY EQU 1EH ; Soft hyphen HARDHY EQU 1FH ; Hard hyphen ; SOFTCR EQU 10000000B+CR ; Soft carriage return SOFTAB EQU 10000000B+TAB ; Soft tab (for ^P) SOFTLF EQU 10000000B+LF ; Soft line feed SOFTFF EQU 10000000B+FFEED ; Soft form feed SOFTBL EQU 10000000B+' ' ; Soft blank ; ; Variable Data Sizes ; TABMAX EQU 15 ; Maximum tabs DECMAX EQU 6 ; Maximum decimal tabs RLRSIZ EQU TABMAX+DECMAX+5 ; Ruler size 08may84 ; ; Standard WordStar List Output Routines ; SIBASE EQU 280h LSTOUT EQU SIBASE+6 ; Prints char in A. ; LSOSTA EQU SIBASE+9 ; Returns output status to A (0 if busy). ; LSTRNG EQU SIBASE+12h ; Send string to list device (count byte ; first, just like console strings). ; ; Printer Driver Entry Points ; ; Note that WordStar expects this table to appear exactly ; in this order. ; PGORG: DB 0 ; Driver model DW PGLEN ; Code length DW PDLEN ; Code + unitialize data length DW $LEN ; String length DW $SYMTAB ; Symbol table address DB 'SIMPLE',0 ; Driver name DW 0 ; Default output file name address JMP PRINITZ ; Initialize printer JMP PRINT ; Print a line JMP PRESUME ; Resume printing JMP PRABORT ; Abort printing JMP PRUNITZ ; Uninitialize when done printing PAGE ; ; Initialize ; ; On entry: HL -> table of printer information ; DE -> user strings ; A is TRUE if form feeds are okay ; ; Note that even though this simple driver does not use all of ; the information, the entire table is defined below. ; ; Do not modify values in the table. WordStar updates the table ; values while printing. ; PRINITZ: SHLD PRTABLE ; Store table address XCHG SHLD PRUSER ; STA PRFFOK ; Form feed flag ; XRA A ; Assume we're at top of first page STA PRLINE ; No lines on page STA PRCOLM ; At leftmost column STA PRFFL ; No form feed lines STA PRHALF ; No half line feed yet STA PRONOFF ; No print controls on STA PRSSIZ ; No string to print STA PR2ND ; No second character STA PREXTX ; Not an extended character STA PRSTRT ; LXI H,XTOGL ; Zero init attr states MVI C,XTOGZ PRINZ1: MOV M,A INX H DCR C JNZ PRINZ1 ; DCR A STA PRLQCH ; Force PRLQ call STA PRTYPX ; No last type for line MVI A,1 STA PRNEXZ ; Skip 1 byte / char ; CALL GETSIZ PRINI1: XRA A RET ; ; Print Value Table Offsets ; PAGTOP EQU 0 ; Top page margin PAGBOT EQU PAGTOP+1 ; Bottom page margin PAGSIZ EQU PAGBOT+1 ; Page size PAGNMT EQU PAGSIZ+1 ; Page number at top PAGON EQU PAGNMT+2 ; Page number on/off flag PAGNMP EQU PAGON+1 ; Column where page number prints HDMAR EQU PAGNMP+1 ; Heading margin FTMAR EQU HDMAR+1 ; Footing margin TBMASK EQU FTMAR+1 ; Tab mask PAGMAR EQU TBMASK+1 ; Left page margin PRNNLQ EQU PAGMAR+1 ; Near letter quality on/off PRNBID EQU PRNNLQ+1 ; Print bidirectional on/off PRNMIC EQU PRNBID+1 ; Microjustified print on/off PRNUNL EQU PRNMIC+1 ; Underline blanks on/off PRNHMI EQU PRNUNL+1 ; Standard character width (in HMI units) PRNVMI EQU PRNHMI+1 ; Standard line height (in VMI units) CHRWID EQU PRNVMI+1 ; Character width (in HMI units) ALTWID EQU CHRWID+1 ; Alternate pitch width (in HMI units) SSROLL EQU ALTWID+1 ; Subscript/superscript roll (in VMI units) LINEHT EQU SSROLL+1 ; Line height (in VMI units) LFMAR EQU LINEHT+1 ; Left margin RTMAR EQU LFMAR+1 ; Right margin PPMAR EQU RTMAR+1 ; Number of tabs TABS EQU PPMAR+1 ; Number of tabs DECS EQU TABS+1+TABMAX ; Number of decimal tabs POCW EQU DECS+1+DECMAX ; Page offset char width HENCW EQU POCW+1 ; Header normal char width HEACW EQU HENCW+1 ; Header alternate char width FONCW EQU HEACW+1 ; Footer normal char width FOACW EQU FONCW+1 ; Footer alternate char width HELH EQU FOACW+1 ; Header line height FOLH EQU HELH+1 ; Footer line height PROP EQU FOLH+1 ; Proportional spacing PAGNUM EQU PROP+1 ; Page number PAGVMI EQU PAGNUM+2 ; VMI units of text on a page (minus margins) VMICNT EQU PAGVMI+2 ; Current VMI count TOPVMI EQU VMICNT+2 ; VMI units in top margin BOTVMI EQU TOPVMI+2 ; VMI units in bottom margin LNHITE EQU BOTVMI+2 ; LINEHT with MS byte zero ALTPCH EQU LNHITE+2 ; Alternate pitch on/off HEPROP EQU ALTPCH+1 ; Header proportional flag HENLQ EQU HEPROP+1 ; Header NLQ FOPROP EQU HENLQ+1 ; Footer proportional flag FONLQ EQU FOPROP+1 ; Footer NLQ SHTBIN EQU FONLQ+1 ; Sheet feeder bin ; PAGE ; ; Print a Line ; ; On entry: HL points to start of a line of characters ; DE contains the number of characters in the line ; A contains the line type code & suppress printing ; flag (MSB of A is 1 to suppress) ; ; Type codes: 0 = line from body of text ; 1 = header line ; 2 = footer line ; ; On exit: A contains a return code ; ; Return code: 0 = done printing line ; 1 = not done printing, printer is busy ; 2 = pause required, operator should resume printing ; PRINT: SHLD PRCHAR ; Store pointer to current char ; XCHG ; Store count SHLD PRCOUNT ; STA PRTYPE ; Store type code ANI 7Fh CPI 3 ; Dot command? JZ PRINI1 ; PUSH PSW LHLD PRTABLE ; Get page offset, space in before the LXI D,PAGMAR ; next printing character DAD D MOV A,M STA PROFST ; MVI A,1 STA PRLEAD ; Leading blank flag XRA A STA PUNDBL ; Not underlining between words ; POP PSW LXI H,PRTYPX MOV B,M MOV M,A CMP B JZ PRIN9 ; ORA A ; Normal text line? JZ PRIN8 ; LXI H,XTOGL+1 ; Clear header/footer attributes MVI C,XTOGZ/2 XRA A PRIN1: MOV M,A INX H INX H DCR C JNZ PRIN1 ; MVI A,1 PRIN8: MOV L,A ; Store print control offset MVI H,0 SHLD PRTYPA CALL PRLQAD ; No change in NLQ print? LDA PRLQPR CMP M JZ PRIN9 ; MVI A,0FFh ; Change NLQ state STA PRLQCH PRIN9: LXI H,PRSTRT ; Not 1st printing line? LDA PRTYPE ORA M JM PRESUME ; MVI M,0FFH ;;; CALL PRBIN JMP PRESUME PAGE ; ; Resume Printing ; ; On exit: A contains a return code ; ; Return code: 0 = done printing line ; 1 = not done printing, printer is busy ; 2 = pause required, operator should resume printing ; ; Note that control must be returned to WordStar if the printer is ; busy so that the user may abort printing from the console. ; Therefore, you must not advance the character pointer or decrement ; the count until after the character has been printed (in case the ; printer is busy). ; PRESUME: LDA PRSSIZ ; Not printing string? ORA A JZ PRES4 ; MOV C,A CALL LSOSTA ; Ready to print string size LHLD PRSPTR JNZ PRES3 ; PRES2: MOV A,C CALL XSIZE ; Save size MVI A,1 JMP PRRET PRES3: MVI A,1 CALL LSOSTA JZ PRES2 ; MOV A,M CALL LSTOUT INX H DCR C JNZ PRES3 ; XRA A STA PRSSIZ PRES4: LDA PR2ND ; No 2nd composite byte? ORA A JZ PRES6 ; CALL PRLO ; Not busy? JNZ PRRET ; PRES5: LXI H,PRCOLM ; Bump posn, no more 2nd char INR M XRA A STA PR2ND JMP PRESUME ; PRES6: LXI H,PRFFL ; No form feed lines left? MOV A,M ORA A JZ PRES7 ; DCR M ; LXI H,$CRLF ; Print CRLF's to next page JMP PRES17 ; PRES7: LDA PRLQCH ; No NLQ change? ORA A JZ PRES8 ; CALL PRLQ ; Change state JMP PRESUME ; PRES8: LHLD PRCOUNT ; Not done printing? MOV A,H ORA L JNZ PRES9 ; CALL GETSIZ ; Get page size JMP PRINI1 ; PRES9: LHLD PRCHAR MOV A,M CPI SOFTFF ; Not a soft form feed? JNZ PRES11 ; LDA PRLINE ; Already at top of page? ORA A JZ PRSKIP ; JMP PRFF ; Form feed ; PRES11: MOV A,M ; 7 bit ASCII ANI 7FH ; LXI H,PRSPEC1 ; Scan special char table MOV B,A PRES12: MOV A,M ; End of table? INX H CPI 0FFH JZ PRES13 ; CMP B JZ PRES13 ; INX H INX H JMP PRES12 ; PRES13: MOV E,M ; Execute special character routine INX H MOV D,M XCHG MOV A,B PCHL ; PRES14: LDA PROFST ; No page offset left? ORA A JZ PRES15 ; CALL PREXOFF ; Not extended character JNZ PRESUME ; MVI A,' ' ; Print spaces to offset left side of page CALL PRLO JNZ PRRET ; LXI H,PROFST DCR M JMP PRESUME ; PRES15: LXI H,PRSPEC2 ; Check 2nd special char table JMP PRES12 ; ; Print character ; PRES16: CPI DEL ; Ignore non printing char? JZ PRSKIP ; CPI ' ' JC PRSKIP ; JNZ PRES19 ; Not a blank? ; CALL PREMAIN ; Only blanks remaining, turn something off? JNZ PRRET ; LHLD PRTYPA ; Not underlining? LXI D,XUNDER DAD D MOV A,M MOV C,A ANI 1 JZ PRES21 ; LHLD PRTABLE ; Continuous underlining? LXI D,PRNUNL DAD D MOV A,M ORA A JNZ PRES21 ; LDA PUNDBL ; Underlining already off? ANI 1 JNZ PRES21 ; MOV A,C ORA A JP PRES21 ; MVI A,1 ; Not underlining blanks STA PUNDBL ; LHLD PRTYPA ; Turn underlining off LXI D,XUNDER DAD D MOV A,M ANI 7FH MOV M,A ; LXI H,$PSOFF PRES17: CALL XSTRNG JMP PRESUME ; PRES19: LDA PRLEAD ; Not the 1st non-blank ANI 1 JZ PRES20 ; CALL PRON ; Not everything on? JNZ PRESUME ; PRES20: XRA A ; No longer leading blank STA PRLEAD ; LDA PUNDBL ; Not suppressing blank underline? ANI 1 JZ PRES21 ; LHLD PRTYPA ; Already on? LXI D,XUNDER DAD D MOV M,A ORA A JM PRES21 ; ORI 80h ; Turn underlining on MOV M,A XRA A ; Underlining a non-blank now STA PUNDBL ; LXI H,$PSON JMP PRES17 ; PRES21: CALL PREXOFF ; Not extended char JNZ PRESUME ; PRE21A: MOV L,B ; Just print char (unless busy) MVI H,0 LXI D,$COMPOS DAD H DAD D MOV A,M ; INX H ; 2nd composite char MOV B,M LXI H,PR2ND MOV M,B ; LXI H,PRCOLM INR M ; CALL PRLO ; Print JNZ PRRET ; MOV A,B ; Composite char? ORA A JNZ PRBS ; PRSKIP: CALL PRNEXT ; Try another char JNZ PRSKIP JMP PRESUME ; PRNEXT: PUSH H PRNEX0: LHLD PRCHAR INX H SHLD PRCHAR ; LHLD PRCOUNT ; Decrement count DCX H SHLD PRCOUNT MOV A,H ORA L JZ PRNEX1 ; LXI H,PRNEXZ ; More than 1 byte? DCR M JNZ PRNEX0 ; PRNEX1: MVI A,1 STA PRNEXZ POP H RET ; ; Dispatch Tables for Special Characters ; PRSPEC1: DB CR DW PRCRLF DB SOFTCR DW PRCRLF DB LF DW PRLF DB SOFTLF DW PRLF DB FFEED DW PRFF DB 'C'-'@' DW PRPAUS DB -1 DW PRES14 ; ; Special chars processed after page offset ; PRSPEC2: DB TAB DW PRTAB DB SOFTAB DW PRTAB DB SOFTBL DW PRBLNK DB 'O'-'@' DW PRBIND DB 'F'-'@' DW PRPHBL DB 'G'-'@' DW PRPHRB DB BS DW PRBS DB 'N'-'@' DW PRNORM DB 'A'-'@' DW PRALT DB 'B'-'@' DW PRBOLD DB 'D'-'@' DW PRDBL DB 'S'-'@' DW PRUNDR DB 'T'-'@' DW PRSUPR DB 'V'-'@' DW PRSUB DB 'X'-'@' DW PRSTRK DB 'Y'-'@' DW PRITAL DB HARDHY DW PRDASH DB SOFTHY DW PRSKIP DB 'Q'-'@' DW PCUSQ DB 'W'-'@' DW PCUSW DB 'E'-'@' DW PCUSE DB 'R'-'@' DW PCUSR DB ESC DW PREXTN DB -1 DW PRES16 ; PRCRLF: CALL PROFF ; Turning things off? JNZ PRESUME ; LHLD PRCOUNT ; No chars after CR? MOV A,H ORA L JZ PRCR ; LHLD PRCHAR ; LF after CR? INX H MOV A,M CPI LF JZ PRCRL1 CPI SOFTLF JNZ PRCR ; PRCRL1: CALL PRNEXT ; Skip CR PRCRL2: XRA A STA PRCOLM LXI H,$CRLF PRCRL3: LDA PRLINE INR A STA PRLINE JMP PSTRNG ; ; Carriage return, no line feed ; PRCR: CALL PROFF ; Turn things off? JNZ PRESUME ; LXI H,$CR XRA A STA PRCOLM JMP PSTRNG ; ; Line feed ; PRLF: CALL PROFF ; Turn things off? JNZ PRESUME ; LXI H,$HLF ; No half line feed string? MOV A,M ORA A JZ PRCRL2 ; LDA PRHALF ; 2nd half line feed? XRI 1 STA PRHALF ORA A JZ PRCRL3 ; JMP PRES17 ; ; Binding space ; PRBIND: LXI H,$CTRLO JMP P1STRNG ; ; Phantom blank ; PRPHBL: LXI H,$CTRLF JMP P1STRNG ; ; Phantom rubout ; PRPHRB: LXI H,$CTRLG JMP P1STRNG ; ; Normal pitch ; PRNORM: LXI H,$NORM JMP PSTRNG ; ; Alternate pitch ; PRALT: LXI H,$ALT JMP PSTRNG ; ; Bold on/off ; PRBOLD: LXI D,XBOLD LXI B,$PBON ; Fall into PRTOGL ; ; Toggle something on/off ; PRTOGL: LHLD PRTYPA DAD D MOV A,M XRI 1 MOV M,A ; LDA PRLEAD ; Only leading blanks so far? ANI 1 JNZ PRTOG3 ; MOV A,M ; Now on? ANI 1 JNZ PRTOG1 ; MOV A,M ; Already off? ORA A JP PRTOG3 ; ANI 7FH ; Mark off MOV M,A LXI H,$SHORT ; Offset to OFF string JMP PRTOG2 ; PRTOG1: MVI A,1 ; On now STA PRONOFF ; MOV A,M ; Already on? ORA A JM PRTOG3 ; ORI 80h MOV M,A LXI H,0 ; Normal string offset PRTOG2: DAD B JMP PSTRNG ; Send control sequence ; PRTOG3: JMP PRSKIP ; Ignore until blanks are done ; ; Doublestrike on/off ; PRDBL: LXI D,XDBL LXI B,$PDON JMP PRTOGL ; ; Underline on/off ; PRUNDR: LXI D,XUNDER LXI B,$PSON XRA A STA PUNDBL JMP PRTOGL ; ; Superscript on/off ; PRSUPR: LXI D,XSUPER LXI B,$PTON JMP PRTOGL ; ; Subscript on/off ; PRSUB: LXI D,XSUB LXI B,$PVON JMP PRTOGL ; ; Strike-out on/off ; PRSTRK: LXI D,XSTRIKE LXI B,$PXON JMP PRTOGL ; ; Italics on/off ; PRITAL: LXI D,XITALIC LXI B,$PYON JMP PRTOGL ; ; Extended character ; PREXTN: LHLD PRCHAR ; ESC xx BESC? INX H INX H MOV M,A CPI BESC JNZ PRSKIP ; MVI A,1 ; Need to send string 1st? CALL PREXST JNZ PRESUME ; MVI A,3 ; Extended character STA PRNEXZ LHLD PRCHAR INX H MOV A,M JMP PRE21A ; ; Tab character (09H) ; PRTAB: ; Tab CALL PREXOFF ; Not extended? JNZ PRESUME LDA PROFST ; MVI A,' ' ; Try to print a blank CALL PRLO JNZ PRRET ; Busy ; LDA PRCOLM ; Increment column INR A STA PRCOLM ; LHLD PRTABLE ; Use tab mask to see if at next stop LXI D,TBMASK DAD D ANA M JNZ PRTAB JMP PRSKIP ; PRFF: ; Form feed CALL PROFF ; Turn things off JNZ PRRET ; Busy ; LDA PRFFOK ; Can't use form feeds? ORA A JZ PRFF1 ; LXI H,@USRFF CALL USTRAD MOV A,M ORA A JNZ PRFF0 ; LXI H,$FF PRFF0: CALL XSTRNG JMP PRFF2 ; PRFF1: LXI H,PRLINE ; Determine remaining lines on page LDA PRPGSZ SUB M JC PRFF2 ; STA PRFFL PRFF2: XRA A ; Top of page STA PRLINE STA PRCOLM JMP PRSKIP ; ; Backspace ; PRBS: LXI H,PRCOLM ; At left stop? MOV A,M ORA A JZ PRSKIP ; DCR M ; Back up LXI H,$BS ; Backspace string JMP PSTRNG ; ; Pause in mid-text ; PRPAUS: CALL PRNEXT LDA PRTYPE ; Inhibit printing? ORA A JM PRESUME ; MVI A,2 ; Return code 2 ORA A RET ; PRBLNK: ; Convert to a blank MVI B,' ' JMP PRES4 ; PRDASH: MVI B,'-' ; Hard Hyphen JMP PRES4 ; PCUSQ: LXI H,@USRQ JMP USTRNG ; PCUSW: LXI H,@USRW JMP USTRNG ; PCUSE: LXI H,@USRE JMP USTRNG ; PCUSR: LXI H,@USRR JMP USTRNG ; ; Send NLQ print status ; PRLQ: XRA A STA PRLQCH CALL PRLQAD MOV A,M STA PRLQPR ; LXI H,$LQON ANI 1 JNZ XSTRNG ; LXI H,$LQOFF JMP XSTRNG ; PRLQAD: LHLD PRTABLE LXI D,PRNNLQ DAD D RET ; ; Check extended character status ; PREXOFF: XRA A ; Not an extended character ; PREXST: LXI H,PREXTX ; No change? CMP M RZ ; MOV M,A ; New state ORA A ; LXI H,$BIDON ORA A JNZ PREXS1 ; LXI H,$BIDOFF PREXS1: CALL XSTRNG LDA PRSSIZ ; Any string? ORA A RET ; ; Table of on/off strings ; PRPRCTL: DW XBOLD,$PBON DW XDBL,$PDON DW XUNDER,$PSON DW XSUPER,$PTON DW XSUB,$PVON DW XSTRIKE,$PXON DW XITALIC,$PYON DW 0 ; ; Turn print controls on or off ; ; on exit: Z if all done, NZ if string pending ; B = $ ; PRON: MVI C,0 ; Offset to ON string MVI A,1 ; On JMP PRO0 ; PROFF: CALL PREXOFF ; Extended chars off RNZ ; MVI C,$SHORT ; Offset to OFF string XRA A ; Off ; PRO0: LXI H,PRONOFF CMP M JZ PRO6 ; LXI H,PRPRCTL PRO1: MOV E,M ; Get attr address INX H MOV D,M INX H MOV A,D ; End of table? ORA E JZ PRO5 ; PUSH H ; Get current attr state LHLD PRTYPA DAD D MOV A,M ANI 1 JZ PRO2A ; Off? ; MOV A,C ; 0 if turning on ORA A JZ PRO3 ; MOV A,M ; Already off? ORA A JP PRO2A ; ANI 7Fh JMP PRO4 PRO2A: POP H INX H INX H JMP PRO1 ; ; Turning on ; PRO3: MOV A,M ; Already on? ORA A JM PRO2A ; ORI 80H ; Mark on ; PRO4: MOV M,A ; New state POP H ; Get pointer to string MOV E,M INX H MOV D,M INX H XCHG PUSH B MVI B,0 DAD B ; Add on/off offset POP B CALL XSTRNG ; AL = 1 from XSTRNG RET ; PRO5: LXI H,PRONOFF ; Change on/off state MOV A,M XRI 1 MOV M,A PRO6: XRA A ; Z RET ; ; Abort Printing ; PRABORT: MVI A,CR ; Print a final CRLF CALL PRLOWT MVI A,LF CALL PRLOWT JMP PRRET PAGE ; ; Uninitialize Printing ; PRUNITZ: LXI H,PRUNI1 ; One last form feed LXI D,1 XRA A CALL PRINT PRUNI0: ORA A RZ CALL PRESUME JMP PRUNI0 ; PRUNI1: DB SOFTFF ; Form feed only if not already top of page PAGE ; ; Check if only blanks remain on line ; ; on exit: NZ if string to be printed ; PREMAIN: LDA PRLEAD ; Leading blank? ANI 1 JNZ PREMA3 ; LHLD PRCOUNT XCHG LHLD PRCHAR JMP PREMA2 ; PREMA1: INX H MOV A,M ANI 7FH CPI SOFTHY ; Control char? JC PREMA2 ; CPI ' ' JZ PREMA2 ; CPI SOFTBL JZ PREMA2 ; CPI SOFTCR JZ PREMA2 ; CPI SOFTLF JNZ PREMA3 ; PREMA2: DCX D ; More? MOV A,D ORA E JNZ PREMA1 ; JMP PROFF ; Turn everything off ; PREMA3: XRA A ; Z no string RET ; ; Get page size ; GETSIZ: PUSH H PUSH D LHLD PRTABLE LXI D,PAGSIZ DAD D MOV A,M STA PRPGSZ POP D POP H RET ; ; Set up to print string at BX ; XSTRNG: PUSH H LDA PRTYPE ; Printing suppressed? ORA A JM XSTRN3 ; XSTRN1: MOV A,M ; No redirection? INX H CPI -1 JNZ XSTRN2 ; PUSH D MOV E,M INX H MOV D,M XCHG POP D JMP XSTRN1 ; XSTRN2: CALL XSIZE XSTRN3: POP H XRA A INR A ; NZ, AL = 1 RET ; ; Store pointer to string to be printed ; ; on entry: HL -> string ; A = length; XSIZE: SHLD PRSPTR STA PRSSIZ RET ; ; Print string at BX ; P1STRNG: LDA PRCOLM INR A STA PRCOLM PSTRNG: CALL XSTRNG JMP PRSKIP ; USTRNG: CALL USTRAD JMP PSTRNG ; USTRAD: PUSH D XCHG LHLD PRUSER DAD D POP D RET ; ; Print a Character ; ; On entry: A contains character to be printed ; ; On exit: A is zero if printed, 1 if busy ; PRLO: PUSH B MOV B,A ; Save char to B ; LDA PRTYPE ; Printing being suppressed? ORA A JM PRL2 ; MVI C,10 ; Go through busy loop up to 10 times ; PRL0: CALL LSOSTA ; Printer ready for a char? JNZ PRL1 ; DCR C ; One more time JNZ PRL0 ; POP B ; Return a 1 since busy XRA A INR A ; (Set Z flag too) RET ; PRL1: MOV A,B ; Print char CALL LSTOUT ; PRL2: POP B ; Return a zero XRA A RET ; ; Print a Character if Possible ; ; On entry: A contains char to be printed ; ; On exit: Char printed if possible ; PRLOWT: LXI H,1000 ; Wait a while for printer to be not busy MOV B,A PRLOW0: MOV A,B ; Try printing it CALL PRLO RZ ; DCX H ; Another try? MOV A,H ORA L JNZ PRLOW0 RET PRRET: RET PGLEN EQU $-PGORG PAGE ; ; Driver Variables ; DATORG: ; PRCHAR: DS 2 ; Pointer to current char PRCOUNT:DS 2 ; Char count PRTYPE: DS 1 ; Type of line PRTYPX: DS 1 ; Prev line type PRTYPA: DS 2 ; Offset to print control toggles ; PRSPTR: DS 2 ; Pointer to string to print PRSSIZ: DS 1 ; Length ; PRLINE: DS 1 ; Current line number PRCOLM: DS 1 ; Current print column PROFST: DS 1 ; Page offset counter PRLEAD: DS 1 ; Leading blank flag PRPGSZ: DS 1 ; Page size ; PRTABLE:DS 2 ; Pointer to WordStar table PRUSER: DS 2 ; Pointer to user area strings ; PRLQPR: DS 1 ; Last NLQ print state PRLQCH: DS 1 ; Change NLQ state ; PREXTX: DS 1 ; Extended character state ; PRFFOK: DS 1 ; Form feed okay flag PRFFL: DS 1 ; CRLF counter PRHALF: DS 1 ; Half line feed counter PRNEXZ: DS 1 ; Character size PR2ND: DS 1 ; Second composed character ; PRONOFF: DS 1 ; Print controls on/off flag ; PUNDBL: DS 1 ; Underlining blanks flag ; PRSTRT: DS 1 ; Printing started flag ; ; Print Control Toggles ; ; Byte for current state, regular text ; XTOGL: XBOLD: DS 2 XDBL: DS 2 XUNDER: DS 2 XSUPER: DS 2 XSUB: DS 2 XSTRIKE: DS 2 XITALIC: DS 2 XTOGZ EQU ($-XTOGL) DATLEN EQU $-DATORG ; Length of uninitialized data PDLEN EQU $-PGORG ; Driver length PAGE $ORG: ; ; String allocation macro ; STRNG MACRO STROFF STPAD SET STROFF-$ IF STPAD AND 0F000H .PRINTX /**** STRING LENGTH ERROR ****/ ENDIF IF STPAD GT 0 DS STPAD ENDIF ENDM ; BTSUPR EQU 1 ; Superscript BTSUB EQU 2 ; Subscript BTCOLR EQU 4 ; Italics/red BTALT EQU 8 ; Alternate width BTUNDR EQU 10H ; Underlining BTSTRK EQU 20H ; Strikeout BTEXT EQU 40H ; Extended character set BTNLQ EQU 80H ; Near letter quality BTPROP EQU 100H ; Proportional BTBOLD EQU 200H ; Boldface BTDBL EQU 400H ; Doublestrike BTENH EQU 800H ; Enhanced (alternate mode boldface) BTCOND EQU 1000H ; Condensed (needs special pass) BTCOMP EQU 2000H ; Printer composed character BSS EQU BTSUPR+BTSUB ; ; Offsets to custom strings in user area ; @USRQ EQU 0 @USRW EQU 25 @USRE EQU 50 @USRR EQU 75 @STRK EQU 100 @USRFF EQU 101 ; ; Offsets into strings and flags ; $SHORT EQU 10 ; Short string length $LONG EQU 25 ; Long string length ; $INIT EQU $ORG+7 $UNINT EQU $INIT+$LONG $ABORT EQU $UNINT+$LONG $CRLF EQU $ABORT+$LONG $CR EQU $CRLF+$SHORT $FF EQU $CR+$SHORT $HLF EQU $FF+$SHORT $BS EQU $HLF+$SHORT $NORM EQU $BS+$SHORT $ALT EQU $NORM+$SHORT $CTRLF EQU $ALT+$SHORT $CTRLG EQU $CTRLF+$SHORT $CTRLO EQU $CTRLG+$SHORT $PBON EQU $CTRLO+$SHORT $PBOFF EQU $PBON+$SHORT $PDON EQU $PBOFF+$SHORT $PDOFF EQU $PDON+$SHORT $PSON EQU $PDOFF+$SHORT $PSOFF EQU $PSON+$SHORT $PTON EQU $PSOFF+$SHORT $PTOFF EQU $PTON+$SHORT $PVON EQU $PTOFF+$SHORT $PVOFF EQU $PVON+$SHORT $PXON EQU $PVOFF+$SHORT $PXOFF EQU $PXON+$SHORT $PYON EQU $PXOFF+$SHORT $PYOFF EQU $PYON+$SHORT $BIDON EQU $PYOFF+$SHORT $BIDOFF EQU $BIDON+$SHORT $LQON EQU $BIDOFF+$SHORT $LQOFF EQU $LQON+$SHORT $BOLD EQU $LQOFF+$SHORT $DOUBLE EQU $BOLD+1 $COMPOS EQU $DOUBLE+1 $SYMTAB EQU $COMPOS+512 ; ; Name of driver ; DB 'SIMPLE' DB 0 ; ; Control strings ; STRNG $INIT DB 1,CR STRNG $UNINT DB 1,CR STRNG $ABORT DB 2,CR,FFEED STRNG $CRLF DB 2,CR,LF STRNG $CR DB 1,CR STRNG $FF DB 1,FFEED STRNG $HLF DB 0 STRNG $BS DB 1,08h STRNG $NORM DB 0 STRNG $ALT DB 0 STRNG $CTRLF DB 1,' ' STRNG $CTRLG DB 1,' ' STRNG $CTRLO DB 1,' ' STRNG $PBON DB 0 STRNG $PBOFF DB 0 STRNG $PDON DB 0 STRNG $PDOFF DB 0 STRNG $PSON DB 0 STRNG $PSOFF DB 0 STRNG $PTON DB 0 STRNG $PTOFF DB 0 STRNG $PVON DB 0 STRNG $PVOFF DB 0 STRNG $PXON DB 0 STRNG $PXOFF DB 0 STRNG $PYON DB 0 STRNG $PYOFF DB 0 STRNG $BIDON DB 0 STRNG $BIDOFF DB 0 STRNG $LQON DB 0 STRNG $LQOFF DB 0 STRNG $BOLD DB 3 STRNG $DOUBLE DB 2 STRNG $COMPOS ; ; Table of composite characters ; entry indexed by WordStar character value ; first byte = printing character or null ; second byte = overstruck character or null ; ; This table is set up for a simple ASCII printer, emulating ; an IBM character set 2. ; UNK EQU '?' COMPOS: DB UNK,0 ; 0 DB UNK,0 ; 1 DB UNK,0 ; 2 DB UNK,0 ; 3, heart DB UNK,0 ; 4, diamond DB UNK,0 ; 5, club DB UNK,0 ; 6, spade DB UNK,0 ; 7 DB UNK,0 ; 8 DB UNK,0 ; 9 DB UNK,0 ; A DB UNK,0 ; B DB UNK,0 ; C DB UNK,0 ; D DB UNK,0 ; E DB UNK,0 ; 0F ; DB UNK,0 ; 10 DB UNK,0 ; 11 DB UNK,0 ; 12 DB UNK,0 ; 13 DB 'PI' ; 14, paragraph symbol DB 'So' ; 15, section mark DB UNK,0 ; 16 DB UNK,0 ; 17 DB UNK,0 ; 18 DB UNK,0 ; 19 DB '->' ; 1A, right arrow DB UNK,0 ; 1B DB UNK,0 ; 1C DB UNK,0 ; 1D DB UNK,0 ; 1E DB UNK,0 ; 1F ; DB ' ',0 ; 20 blank DB '!',0 ; 21 DB '"',0 ; 22 DB '#',0 ; 23 DB '$',0 ; 24 DB '%',0 ; 25 DB '&',0 ; 26 DB "'",0 ; 27 DB '(',0 ; 28 DB ')',0 ; 29 DB '*',0 ; 2A DB '+',0 ; 2B DB ',',0 ; 2C DB '-',0 ; 2D DB '.',0 ; 2E DB '/',0 ; 2F ; DB '0',0 ; 30 DB '1',0 ; 31 DB '2',0 ; 32 DB '3',0 ; 33 DB '4',0 ; 34 DB '5',0 ; 35 DB '6',0 ; 36 DB '7',0 ; 37 DB '8',0 ; 38 DB '9',0 ; 39 DB ':',0 ; 3A DB ';',0 ; 3B DB '<',0 ; 3C DB '=',0 ; 3D DB '>',0 ; 3E DB '?',0 ; 3F ; DB '@',0 ; 40 DB 'A',0 ; 41 DB 'B',0 ; 42 DB 'C',0 ; 43 DB 'D',0 ; 44 DB 'E',0 ; 45 DB 'F',0 ; 46 DB 'G',0 ; 47 DB 'H',0 ; 48 DB 'I',0 ; 49 DB 'J',0 ; 4A DB 'K',0 ; 4B DB 'L',0 ; 4C DB 'M',0 ; 4D DB 'N',0 ; 4E DB 'O',0 ; 4F ; DB 'P',0 ; 50 DB 'Q',0 ; 51 DB 'R',0 ; 52 DB 'S',0 ; 53 DB 'T',0 ; 54 DB 'U',0 ; 55 DB 'V',0 ; 56 DB 'W',0 ; 57 DB 'X',0 ; 58 DB 'Y',0 ; 59 DB 'Z',0 ; 5A DB '[',0 ; 5B DB '\',0 ; 5C DB ']',0 ; 5D DB '^',0 ; 5E DB '_',0 ; 5F ; DB '`',0 ; 60 DB 'a',0 ; 61 DB 'b',0 ; 62 DB 'c',0 ; 63 DB 'd',0 ; 64 DB 'e',0 ; 65 DB 'f',0 ; 66 DB 'g',0 ; 67 DB 'h',0 ; 68 DB 'i',0 ; 69 DB 'j',0 ; 6A DB 'k',0 ; 6B DB 'l',0 ; 6C DB 'm',0 ; 6D DB 'n',0 ; 6E DB 'o',0 ; 6F ; DB 'p',0 ; 70 DB 'q',0 ; 71 DB 'r',0 ; 72 DB 's',0 ; 73 DB 't',0 ; 74 DB 'u',0 ; 75 DB 'v',0 ; 76 DB 'w',0 ; 77 DB 'x',0 ; 78 DB 'y',0 ; 79 DB 'z',0 ; 7A DB '{',0 ; 7B DB '|',0 ; 7C DB '}',0 ; 7D DB '~',0 ; 7E DB UNK,0 ; 7F ; DB 'C,' ; 80 c, DB 'u~' ; 81 u umlaut DB "e'" ; 82 e' DB 'a^' ; 83 a^ DB 'a~' ; 84 a umlaut DB 'a`' ; 85 a` DB 'a[' ; 86 a ring DB 'c,' ; 87 c, DB 'e^' ; 88 e^ DB 'e~' ; 89 e umlaut DB 'e`' ; 8A e` DB 'i~' ; 8B i umlaut DB 'i^' ; 8C i^ DB 'i`' ; 8D i` DB 'A~' ; 8E A umlaut DB 'A[' ; 8F A ring ; DB "E'" ; 90 E' DB 'ae' ; 91 ae DB 'AE' ; 92 AE DB 'o^' ; 93 o^ DB 'o~' ; 94 o umlaut DB 'o`' ; 95 o` DB 'u^' ; 96 u^ DB 'u`' ; 97 u` DB 'y~' ; 98 y umlaut DB 'O~' ; 99 O umlaut DB 'U~' ; 9A U umlaut DB 'c|' ; 9B cent symbol DB 'L-' ; 9C British pound DB 'Y-' ; 9D Japanese yen DB 'Pt' ; 9E Spanish peseta DB 'S-' ; 9F curly f ; DB "a'" ; A0 a' DB "i'" ; A1 i' DB "o'" ; A2 o' DB "u'" ; A3 u' DB 'n~' ; A4 n~ DB 'N~' ; A5 N~ DB 'a_' ; A6 a_ DB 'o_' ; A7 o_ DB '?',0 ; A8 upside down ? DB '/',0 ; A9 upper left corner DB '\',0 ; AA upper right corner DB '12' ; AB 1/2 DB '14' ; AC 1/4 DB '!',0 ; AD upside down ! DB '<<' ; AE << DB '>>' ; AF >> ; DB 'HI' ; B0 1/4 density block DB 'HX' ; B1 1/3 density block DB 'H*' ; B2 1/2 density block DB '|',0 ; B3 single vertical DB '|',0 ; B4 right vertical -| 1V 1H DB '|',0 ; B5 right vertical =| 1V 2H DB '|',0 ; B6 right vertical -|| 2V 1H DB '\',0 ; B7 upper right 2V 1H DB '\',0 ; B8 upper right 1V 2H DB '|',0 ; B9 right vertical =|| 2V 2H DB '|',0 ; BA double vertical DB '\',0 ; BB upper right 2V 2H DB '/',0 ; BC bottom right 2V 2H DB '/',0 ; BD bottom right 2V 1H DB '/',0 ; BE bottom right 1V 2H DB '\',0 ; BF uppper right 1V 1H ; DB '\',0 ; C0 bottom left 1V 1H DB '-',0 ; C1 bottom 1V 1H DB '-',0 ; C2 top 1V 1H DB '|',0 ; C3 left 1V 1H DB '-',0 ; C4 horizontal 1H DB '-|' ; C5 cross 1V 1H DB '|',0 ; C6 left 1V 2H DB '|',0 ; C7 left 2V 1H DB '\',0 ; C8 bottom left 2V 2H DB '/',0 ; C9 top left 2V 2H DB '-',0 ; CA bottom 2V 2H DB '-',0 ; CB top 2V 2H DB '|',0 ; CC left 2V 2H DB '-',0 ; CD horizontal 2H DB '-|' ; CE cross 2V 2H DB '-',0 ; CF bottom 1V 2H ; DB '-',0 ; D0 bottom 2V 1H DB '-',0 ; D1 top 1V 2H DB '-',0 ; D2 top 2V 1H DB '\',0 ; D3 bottom left 2V 1H DB '\',0 ; D4 bottom left 1V 2H DB '/',0 ; D5 top left 1V 2H DB '/',0 ; D6 top left 2V 1H DB '-|' ; D7 cross 2V 1H DB '-|' ; D8 cross 1V 2H DB '/',0 ; D9 bottom right 1V 1H DB '/',0 ; DA top left 1V 1H DB 'H*' ; DB solid block DB 'mw' ; DC solid bottom half DB '|',0 ; DD solid left half DB '|',0 ; DE solid right half DB '~^' ; DF solid top half ; DB 'a',0 ; E0 alpha DB 'B,' ; E1 beta DB 'g',0 ; E2 gamma DB 'n-' ; E3 pi DB 'E',0 ; E4 epsilon DB 'r',0 ; E5 rho DB 'u.' ; E6 mu DB 't',0 ; E7 tau DB 'oI' ; E8 oI DB 'O-' ; E9 O- DB 'n_' ; EA ohm DB 's',0 ; EB sigma DB 'o|' ; EC o| DB 'O/' ; ED O/ DB 'E',0 ; EE round E DB 'n',0 ; EF inverted U ; DB '=_' ; F0 =_ DB '+_' ; F1 +_ DB '>_' ; F2 >_ DB '<_' ; F3 <_ DB 'f',0 ; F4 upper integral DB 'j',0 ; F5 lower integral DB '-:' ; F6 divide by DB '~-' ; F7 ~_ DB 'o',0 ; F8 degree DB '.',0 ; F9 high . DB '-',0 ; FA short - DB 'v-' ; FB v- divide by DB 'n',0 ; FC superscript n DB '2',0 ; FD superscript 2 DB "'`" ; FE small centered block DB UNK,0 ; FF not used STRNG $SYMTAB ; ; Symbol table ; ; WORD symbol count ; REPEAT 6 BYTES symbol name ; WORD symbol address ; WORD symbol storage size ; DW SYMCNT ; DB 'DATA ' ; All strings and tables DW $ORG DW $LEN ; DB '$START' ; Initialize string DW $INIT DW $LONG ; DB '$DONE ' ; Uninitialize string DW $UNINT DW $LONG DB '$QUIT ' ; Abort string DW $ABORT DW $LONG DB 'CRLF ' DW $CRLF DW $SHORT DB 'CRET ' DW $CR DW $SHORT DB '$FFEED' DW $FF DW $SHORT DB 'HALFLF' DW $HLF DW $SHORT DB 'BACKSP' DW $BS DW $SHORT DB 'NORMWD' DW $NORM DW $SHORT DB 'ALTRWD' DW $ALT DW $SHORT DB 'PHSP ' DW $CTRLF DW $SHORT DB 'PHRUB ' DW $CTRLG DW $SHORT DB 'BINDSP' DW $CTRLO DW $SHORT DB 'BLDON ' DW $PBON DW $SHORT DB 'BLDOFF' DW $PBOFF DW $SHORT DB 'DBLON ' DW $PDON DW $SHORT DB 'DBLOFF' DW $PDOFF DW $SHORT DB 'UNDON ' DW $PSON DW $SHORT DB 'UNDOFF' DW $PSOFF DW $SHORT DB 'SPRON ' DW $PTON DW $SHORT DB 'SPROFF' DW $PTOFF DW $SHORT DB 'SUBON ' DW $PVON DW $SHORT DB 'SUBOFF' DW $PVOFF DW $SHORT DB 'STKON ' DW $PXON DW $SHORT DB 'STKOFF' DW $PXOFF DW $SHORT DB 'ITLON ' DW $PYON DW $SHORT DB 'ITLOFF' DW $PYOFF DW $SHORT DB 'EXTON ' DW $BIDON DW $SHORT DB 'EXTOFF' DW $BIDOFF DW $SHORT DB 'NLQON ' DW $LQON DW $SHORT DB 'NLQOFF' DW $LQOFF DW $SHORT DB 'COMPOS' DW $COMPOS DW 512 ; DB 'CODE ' ; Model 1 code DW PGORG DW PGLEN SYMCNT EQU ($-$SYMTAB)/10 $LEN EQU $-$ORG END