ain@j.cc.purdue.edu (Patrick White) (01/10/88)
Program Name: tek4695 printer driver Submitted By: Phil Staub <phils%tekig.tek.com@relay.cs.net> Summary: This is an updated tek4695 printer driver -- fixes some bugs and adds some new capabilities. Poster Boy: Pat White (ain@j.cc.purdue.edu) Untested. NOTES: I didn't assemble this program, so it is untested. -- Pat White (co-moderator comp.sources/binaries.amiga) UUCP: j.cc.purdue.edu!ain BITNET: PATWHITE@PURCCVM PHONE: (317) 743-8421 U.S. Mail: 320 Brown St. apt. 406, West Lafayette, IN 47906 ======================================== Here are the sources for an updated version of a Tektronix 4695 printer driver I wrote a while back. It fixes a few bugs and adds a few new capabilities. One of the bugs it fixes sort of prompted one of the new features: It now supports the set foreground and set background color escape sequences for text printing. These escape sequences used to crash the machine. Another bug fixed is that I had some reports of some programs guru'ing when finishing up a graphic dump. This was apparently due to function #4 being called in render() more than once without an intervening call on the function which allocates the buffers (I think it's function 1). Since this function frees a couple of buffers, it's not nice to call the function multiple times. Also, I re-arranged render() to minimize the overhead in plotting pixels, since that happens *many* times. I'm not sure how much effect this has, but at least it "feels" a little quicker. Finally, I added support for underlined characters in text mode. This is something which I don't think was there before, but I can't remember for sure. Enjoy Phil ============================== #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # data.c # dospecial.c # include.asm # include.c # init.asm # macros.i # makefile # printertag.asm # render.c # wait.asm # This archive created: Mon Dec 14 22:45:05 1987 cat << \SHAR_EOF > data.c /* Tektronix 4695 command table */ /****** printer.device/printers/Tektronix_4695_functions ******************** * * Name * Tektronix 4695 functions implemented: * * aIND, aNEL, * aSLPP, * aTBC0, aTBC3, aTBCALL, aTBSALL * * special functions implemented: * aRIN, aSLRM, aSFC, aSBC * **************************************************************************/ char *CommandTable[] = { "\377", /* reset RIS */ "\377", /* initialize RIN */ "\012", /* index IND */ "\015\012", /* new line NEL */ "\377", /* rev index RI */ "\021", /* norm ch set SGR0 */ "\377", /* italics on SGR3 */ "\377", /* italics off SGR23 */ "\022", /* underline on SGR4 */ "\021", /* underlin off SGR24 */ "\377", /* bold on SGR1 */ "\377", /* bold off SGR22 */ "\377", /* set fore col SFC */ "\377", /* set back col SBC */ "\377", /* norm space SHORP0 */ "\377", /* elite on SHORP2 */ "\377", /* elite off SHORP1 */ "\377", /* fine on SHORP4 */ "\377", /* fine off SHORP3 */ "\377", /* enlarged on SHORP6 */ "\377", /* enlarged off SHORP5 */ "\377", /* shadow print on DEN6 */ "\377", /* shadow print off DEN5 */ "\377", /* double strike on DEN4 */ "\377", /* double strike off DEN3 */ "\377", /* NLQ on DEN2 */ "\377", /* NLQ off DEN1 */ "\377", /* superscript on SUS2 */ "\377", /* superscript off SUS1 */ "\377", /* subscript on SUS4 */ "\377", /* subscript off SUS3 */ "\377", /* normalize the line SUS0 */ "\377", /* partial line up PLU */ "\377", /* partial line down PLD */ "\377", /* US Character Set FNT0 */ "\377", /* French Character set FNT1 */ "\377", /* German Character setFNT2 */ "\377", /* UK character set FNT3 */ "\377", /* Danish I character set FNT4 */ "\377", /* Swedish character set FNT5 */ "\377", /* Italian char set FNT6 */ "\377", /* Spanish char set FNT7 */ "\377", /* Jap char set FNT8 */ "\377", /* Norw char set FNT9 */ "\377", /* Danish II char set FNT10 */ "\377", /* Prop on PROP2 */ "\377", /* Prop off PROP1 */ "\377", /* prop clear PROP0 */ "\377", /* set prop offset TSS */ "\377", /* auto left justify JFY5 */ "\377", /* auto right justify JFY7 */ "\377", /* auto full justify JFY6 */ "\377", /* auto justify off JFY0 */ "\377", /* letter space (justify) JFY3 */ "\377", /* word fill (auto center) JFY1 */ "\377", /* 8LPI VERP0 */ "\377", /* 6LPI VERP1 */ "\377", /* set lines/page SLPP */ "\377", /* perf skip PERF */ "\377", /* perf skip off PERF0 */ "\377", /* left margin set LMS */ "\377", /* right margin set RMS */ "\377", /* top margin set TMS */ "\377", /* bottom margin set BMS */ "\377", /* set t&b margin STBM */ "\377", /* set l&r margin SLRM */ "\377", /* clear all margins CAM */ "\377", /* horizontal tab set HTS */ "\377", /* vertical tab set VTS */ "\377", /* clear horiz tab TBC0 */ "\0332", /* clear all horiz tabs TBC3 */ "\377", /* clear vert tab TBC1 */ "\377", /* clear all vert tabs TBC4 */ "\0332", /* clear all tabs TBCALL */ "\377", /* set default tabs TBSALL */ "\377" /* extended commands EXTEND */ }; SHAR_EOF cat << \SHAR_EOF > dospecial.c /* Tektronix 4695 special printer functions */ /******* printer.device/printers/Tektronix_4695_special_functions ********** * * Name * Tektronix 4695 special functions implemented: * * aRIN, aSLRM, aSFC, aSBC *************************************************************************/ #include <exec/types.h> #include <devices/printer.h> #include <devices/prtbase.h> #include <clib/macros.h> extern struct PrinterData *PD; long DoSpecial(command,outputBuffer,vline,currentVMI,crlfFlag,Parms) char *outputBuffer; UWORD *command; BYTE *vline; UBYTE *currentVMI; BYTE *crlfFlag; UBYTE Parms[]; { static BYTE FGColorTable[] = {'1','3','5','4','7','2','6','0','1','1'}; static BYTE BGColorTable[] = {'1','3','5','4','7','2','6','0','0','0'}; extern UBYTE TextColors; char buf[80], shortbuf[3]; buf[0] = shortbuf[2] = '\0'; switch(*command) { case aRIN: { /* default text color */ TextColors = 0x70; /* white background, black text */ strcat(buf,"\r\n"); } /* fall through to set default tabs */ case aTBSALL: { Parms[0] = (PD->pd_Preferences.PrintLeftMargin); Parms[1] = (PD->pd_Preferences.PrintRightMargin); /* fall through to set the margins and default tabs */ } case aSLRM: { /* actually sets both left and right margins and default tabs */ /* default tabs are set every 8 columns */ register int LeftMargin = Parms[0]; register int RightMargin = 100 - Parms[1]; register int count; /* ensure that both margins are valid: * odd numbers * 5 <= margin <= 95 * (we assume that left margin is to left of right margin) */ LeftMargin = MIN(95,(MAX(5,(LeftMargin | 1)))); RightMargin = MIN(95,(MAX(5,(RightMargin | 1)))); /* Build the initialization string */ strcat(buf,"\033W10\033H"); /* put in the number of tabs */ count = (Parms[1] - LeftMargin) / 8; shortbuf[0] = (count / 10) + '0'; shortbuf[1] = (count % 10) + '0'; strcat(buf,shortbuf); /* continue by putting in the left margin */ shortbuf[0] = (LeftMargin / 10) + '0'; shortbuf[1] = (LeftMargin % 10) + '0'; strcat(buf,shortbuf); /* now insert tab specifications */ while (count--) strcat(buf,"08"); /* finally put in the right margin */ shortbuf[0] = (RightMargin / 10) + '0'; shortbuf[1] = (RightMargin % 10) + '0'; strcat(buf,shortbuf); /* now copy into the output buffer and return the length */ strcpy(outputBuffer,buf); return(strlen(buf)); } case aSFC: if (Parms[0] < 40) TextColors = ((TextColors)&240)+(Parms[0]-30); /* fall through to aSBC */ case aSBC: { register char *p_out = outputBuffer; if (Parms[0] >= 40) TextColors = ((TextColors)&15)+((Parms[0]-40)*16); *p_out++ = '\033'; *p_out++ = 'C'; *p_out++ = FGColorTable[TextColors&15]; *p_out = BGColorTable[((TextColors&240)/16)]; return(4); /* we just stuffed 4 characters into the output * buffer. now we return the length */ } case aSLPP: { char buf[5]; int len = (Parms[0]+5)/6; /* len is in inches, * Parms is in lines */ strcpy(buf,"\033L"); buf[2] = (len / 10) + '0'; buf[3] = (len % 10) + '0'; strcpy(outputBuffer,buf); return(4); } case aRIS: PD->pd_PWaitEnabled = 253; break; default: break; } return(0); } /* turn this on to get a routine to print things to debugging terminal */ /* db(num) { kprintf("%ld\n",num); while (KGetChar() != '\r') ; } */ SHAR_EOF cat << \SHAR_EOF > include.asm ;:ts=8 far code far data public .begin dseg end SHAR_EOF cat << \SHAR_EOF > include.c #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/memory.h> #include "devices/printer.h" #include "devices/prtbase.h" #include <functions.h> SHAR_EOF cat << \SHAR_EOF > init.asm far code far data ; ; Excerpt from Amiga ROM Kernel Reference Manual: Libraries and ; Devices. Used by permission, 1987, Phil Staub. ; ;************************************************************************** ; * ; Copyright 1985, Commodore-Amiga Inc. All rights reserved. * ; No part of this program may be reproduced, transmitted * ; transcribed, stored in retrieval system, or translated into * ; any language or computer language, in any form or by any means, * ; electronic, mechanical, magnetic, optical, chemical, * ; manual or ohterwise, without the prior written permission of * ; Commodore-Amiga Incorporated, 983 University Ave. Building #D, * ; Los Gatos, California, 95030 * ; * ;************************************************************************** section printer ; included files include "exec/types.i" include "exec/nodes.i" include "exec/lists.i" include "exec/memory.i" include "exec/ports.i" include "exec/libraries.i" include "macros.i" ; imported functions XREF_EXE CloseLibrary XREF_EXE OpenLibrary XREF _AbsExecBase XREF _PEDData ; exported globals XDEF _Init XDEF _Expunge XDEF _Open XDEF _Close XDEF _PD XDEF _PED XDEF _SysBase XDEF _DOSBase XDEF _GfxBase XDEF _IntuitionBase XDEF _TextColors ; Added to avoid using currentVMI to hold color ;*********************************************** section printer,data _PD DC.L 0 _PED DC.L 0 _SysBase DC.L 0 _DOSBase DC.L 0 _GfxBase DC.L 0 _IntuitionBase DC.L 0 _TextColors DC.L 0 ; Added to avoid using currentVMI to hold color ;*********************************************** section printer,code _Init: move.l 4(a7),_PD lea _PEDData(pc),a0 move.l a0,_PED move.l a6,-(a7) move.l _AbsExecBase,a6 move.l a6,_SysBase ; open the dos library lea DLName(pc),a1 moveq #0,d0 CALLEXE OpenLibrary move.l d0,_DOSBase beq.l initDLErr ; open the graphics library lea GLName(pc),a1 moveq #0,d0 CALLEXE OpenLibrary move.l d0,_GfxBase beq.l initGLErr ; open the intuition library lea ILName(pc),a1 moveq #0,d0 CALLEXE OpenLibrary move.l d0,_IntuitionBase beq.l initILErr move.b #$70,_TextColors ; set default text color: black on white moveq #0,d0 pdiRTS: move.l (a7)+,a6 rts initPAErr: move.l _IntuitionBase,a1 LINKEXE CloseLibrary initILErr: move.l _GfxBase,a1 LINKEXE CloseLibrary initGLErr: move.l _DOSBase,a1 LINKEXE CloseLibrary initDLErr: moveq #-1,d0 bra.s pdiRTS ILName: dc.b 'intuition.library' dc.b 0 DLName: dc.b 'dos.library' dc.b 0 GLName: dc.b 'graphics.library' dc.b 0 ds.w 0 ; _Expunge: move.l _IntuitionBase,a1 LINKEXE CloseLibrary move.l _GfxBase,a1 LINKEXE CloseLibrary move.l _DOSBase,a1 LINKEXE CloseLibrary _Open: moveq #0,d0 rts _Close: moveq #0,d0 rts end SHAR_EOF cat << \SHAR_EOF > macros.i ;************************************************************************** ; printer device macro definitions ;************************************************************************** ; external definition macros XREF_EXE macro XREF _LVO\1 endm XREF_DOS macro XREF _LVO\1 endm XREF_GFX macro XREF _LVO\1 endm XREF_ITU macro XREF _LVO\1 endm ; library dispatch macros CALLEXE macro CALLLIB _LVO\1 endm LINKEXE macro LINKLIB _LVO\1,_SysBase endm CALLDOS macro LINKLIB _LVO\1,_DOSBase endm LINKGFX macro LINKLIB _LVO\1,_GfxBase endm LINKITU macro LINKLIB _LVO\1,_IntuitionBase endm SHAR_EOF cat << \SHAR_EOF > makefile OBJS = printertag.o init.o wait.o data.o dospecial.o render.o CFLAGS = +P +Q +Iinclude.pre all: include.pre Tektronix_4695 Tektronix_4695: $(OBJS) ln -o Tektronix_4695 $(OBJS) -lcl32 include.pre: include.c cc -a +P +Q +Hinclude.pre include.c SHAR_EOF cat << \SHAR_EOF > printertag.asm far code far data ; ; Excerpt from Amiga ROM Kernel Reference Manual: Libraries and ; Devices. Used by permission, 1987, Phil Staub. ; ;************************************************************************** ; * ; Copyright 1985, Commodore-Amiga Inc. All rights reserved. * ; No part of this program may be reproduced, transmitted * ; transcribed, stored in retrieval system, or translated into * ; any language or computer language, in any form or by any means, * ; electronic, mechanical, magnetic, optical, chemical, * ; manual or ohterwise, without the prior written permission of * ; Commodore-Amiga Incorporated, 983 University Ave. Building #D, * ; Los Gatos, California, 95030 * ; * ;************************************************************************** section printer include "exec/types.i" include "exec/nodes.i" include "exec/strings.i" include "devices/prtbase.i" xref _Init xref _Expunge xref _Open xref _Close xref _CommandTable xref _DoSpecial xref _Render xdef _PEDData xdef .begin xdef _main VERSION EQU 31 REVISION EQU 24 .begin: _main: moveq #0,d0 rts dc.w VERSION dc.w REVISION _PEDData: dc.l printerName dc.l _Init dc.l _Expunge dc.l _Open dc.l _Close dc.b PPC_COLORGFX dc.b PCC_YMCB dc.b 80 dc.b 1 dc.w 4 dc.l 1024 dc.l 0 dc.w 120 dc.w 120 dc.l _CommandTable dc.l _DoSpecial dc.l _Render dc.l 60 dc.l 0 printerName: dc.b "Tektronix 4695" dc.b 0 end SHAR_EOF cat << \SHAR_EOF > render.c /**********************************************************************/ #include <exec/types.h> #include <exec/nodes.h> #include <exec/lists.h> #include <exec/memory.h> #include "devices/printer.h" #include "devices/prtbase.h" #include <functions.h> extern struct PrinterData *PD; /* for the Tektronix 4695 */ long Render(ct,x,y,status) register ULONG ct; /* was UBYTE for Lattice compiler */ register ULONG x,y; /* was UWORD for Lattice compiler */ ULONG status; /* was UBYTE for Lattice compiler */ { static UWORD ROWSIZE; static UWORD COLORSIZE; static UWORD BUFSIZE; static UWORD colors[4]; static BYTE huns,tens,ones; static UWORD bufptr; static UBYTE *initbuf; register struct PrinterData *pp = PD; register UBYTE *ptr; UWORD i; BYTE err; /* placing pixels in the row buffers is a *very* time critical task. * for this reason, we do this here, rather than in the switch below. */ if ((UBYTE)status == 1) { /* put pixel in buffer (called a max of 16384 * times per print cycle) */ register UWORD i; i = bufptr+(UWORD)x/8+((UWORD)y&3)*ROWSIZE+colors[(UBYTE)ct]; PD->pd_PrintBuf[i] |= (1 << (7-((UWORD)x&7))); return(0); } switch((UBYTE)status) { /* each case in this switch exits via a "return", so * there is no "break" */ case 0: /* alloc memory for printer buffer (uses dbl buf) */ ROWSIZE = ((UWORD)x+7)/8; huns = ROWSIZE/100; tens = (ROWSIZE - huns*100)/10; ones = (ROWSIZE - huns*100 - tens*10); ROWSIZE += 6; /* escape sequence overhead */ COLORSIZE = ROWSIZE*4; /* one for each color */ BUFSIZE = COLORSIZE*4+2; /* 4 colors + CR/LF */ /* colors we get are swizzled from the way we *want them */ colors[0] = 6; /* start of color 0 */ colors[1] = COLORSIZE*2+6; /* start of color 1 */ colors[2] = COLORSIZE+6; /* start of color 2 */ colors[3] = COLORSIZE*3+6; /* start of color 3 */ /* allocate a buffer which is used to init the * print buffers, then initialize it */ initbuf = (UBYTE *) AllocMem((long)BUFSIZE,(long)MEMF_PUBLIC); if(err = (initbuf==0)) return(err); /* clear and init buffer */ ptr = initbuf; for (i = 0; i < BUFSIZE; i++) *ptr++ = 0; for (i = 0; i < 16; i++) { ptr = &initbuf[i*ROWSIZE]; *ptr++ = '\033'; *ptr++ = 'I'; *ptr++ = i+'0'; *ptr++ = huns + '0'; *ptr++ = tens + '0'; *ptr++ = ones + '0'; } initbuf[BUFSIZE-2] = '\033'; initbuf[BUFSIZE-1] = 'A'; /* try to allocate the print buffer */ pp->pd_PrintBuf = (UBYTE *) AllocMem((long)BUFSIZE*2,(long)MEMF_PUBLIC); if(err = (pp->pd_PrintBuf==0)) return(err); /* 1 second delay */ if(err = PWait(1L,0L)) return(err); /* set up for first buffer */ bufptr = 0; return(0); case 2: /* dump buffer to printer */ if (err = (*(pp->pd_PWrite))(&pp->pd_PrintBuf[bufptr], (long)BUFSIZE)) return (err); bufptr = BUFSIZE - bufptr; return(0); case 3: /* re-initialize a buffer */ { register UBYTE *s, *d; register UWORD i; d = &pp->pd_PrintBuf[bufptr]; s = initbuf; for (i = 0; i < BUFSIZE; i++) *d++ = *s++; return(0); } case 4: /* free the print buffer memory */ err = (*(pp->pd_PBothReady))(); if (pp->pd_PrintBuf) { FreeMem(pp->pd_PrintBuf,(long)BUFSIZE*2L); pp->pd_PrintBuf = 0; } if (initbuf) { FreeMem(initbuf,(long)BUFSIZE); initbuf = 0; } return(err); default: return(0); } } SHAR_EOF cat << \SHAR_EOF > wait.asm far code far data section printer include 'exec/types.i' include 'exec/ports.i' include 'exec/devices.i' include 'exec/io.i' include 'devices/timer.i' XREF_EXE MACRO XREF _LVO\1 ENDM XREF_DOS MACRO XREF _LVO\1 ENDM XREF_GFX MACRO XREF _LVO\1 ENDM XREF_ITU MACRO XREF _LVO\1 ENDM CALLEXE MACRO CALLLIB _LVO\1 ENDM LINKEXE MACRO LINKLIB _LVO\1,_SysBase ENDM LINKDOS MACRO LINKLIB _LVO\1,_DOSBase ENDM LINKGFX MACRO LINKLIB _LVO\1,_GfxBase ENDM LINKITU MACRO LINKLIB _LVO\1,_IntuitionBase ENDM INCLUDE 'devices/prtbase.i' XREF_EXE Forbid XREF_EXE Permit XREF_EXE WaitIO XREF _SysBase XREF _PD XDEF _PWait _PWait: movem.l a4/a6,-(a7) move.l _PD,a4 move.l pd_PBothReady(a4),a0 jsr (a0) tst.l d0 bne.s error lea pd_TIOR(a4),a1 move.w #TR_ADDREQUEST,IO_COMMAND(a1) move.l 12(a7),IOTV_TIME+TV_SECS(a1) move.l 16(a7),IOTV_TIME+TV_MICRO(a1) clr.b IO_FLAGS(a1) move.l IO_DEVICE(a1),a6 jsr DEV_BEGINIO(a6) LINKEXE Forbid lea pd_TIOR(a4),a1 LINKEXE WaitIO LINKEXE Permit moveq #0,d0 tst.l d0 error: movem.l (a7)+,a4/a6 rts end SHAR_EOF # End of shell archive exit 0