glu@gypsy.UUCP (03/09/86)
Here is a printer driver for Okidata ML92 printers. I use it with my
parallel printer. It does both alpha and graphics and is written according
to the guidelines in ROM Kernel Manual 1.1. I also included a routine to
dump an entire workbench screen on the printer (copied from Fred Fish's
disk #5, added routines to make it link and run).
You have to separate the following file into 11 different files (including
a makefile to compile and link it).
I will probably improve the printer driver (i.e. optimize graphics printing
because it's real slooooow, provide italics fonts for alpha printing and
support some more of the suggested escape sequences in ROM Kernel Manual)
If somebody else enhances it, please let me participate in your improvements
My address is
Raimund Gluecker
26 Trafalgar Court
Lawrenceville, NJ 08648
(609) 896-4860 (nights) (609) 734-6536 (days - eastern time)
Since I'm not a UNIX Guru, I can't figure out my electronic mail
address. If you do not have a C compiler, you might as well send
me $6 and I'll copy the stuff on a disk and send it to you.
----- cut ----- cut ----- cut ----- cut ----- cut ----- cut ----- cut -----
*****************************************************************************
/* data.c data.c data.c data.c data.c data.c data.c data.c data.c data.c */
*****************************************************************************
/* Command Table Data for Okidata ML92 */
char *CommandTable[] = {
"\030\033\011\n\033%C000",
/* reset RIS */
"\377", /* initialize RIN */
"\012", /* lf IND */
"\015\012", /* return, lf NEL */
"\377", /* reverse lf RI */
"\033I\033D", /* normal character set SGR0 */
"\377", /* italics on SGR3 */
"\377", /* italics off SGR23 */
"\033C", /* underline on SGR4 */
"\033D", /* underline off SGR24 */
"\033H\033T", /* boldface on SGR1 */
"\033I", /* boldface off SGR22 */
"\377", /* set foreground color SFC */
"\377", /* set background color SBC */
"\036", /* normal pitch SHORP0 */
"\034", /* elite on SHORP2 */
"\036", /* elite off SHORP1 */
"\035", /* condensed (fine) on SHORP4 */
"\036", /* condensed off SHORP3 */
"\037", /* enlarged on SHORP6 */
"\036", /* enlarged off SHORP5 */
"\377", /* shadow print on DEN6 */
"\377", /* shadow print off DEN5 */
"\377", /* doublestrike on DEN4 */
"\377", /* doublestrike off DEN3 */
"\0331", /* Near Letter Quality on DEN2 */
"\0330", /* Near Letter Quality off DEN1 */
"\033J", /* superscript on SUS2 */
"\033K", /* superscript off SUS1 */
"\033L", /* subscript on SUS4 */
"\033M", /* subscript off SUS3 */
"\033K\033M", /* normalize SUS0 */
"\377", /* partial line up PLU */
"\377", /* partial line down PLD */
"\377", /* US char set FNT0 */
"\377", /* French char set FNT1 */
"\377", /* German char set FNT2 */
"\377", /* UK char set FNT3 */
"\377", /* Danish I char set FNT4 */
"\377", /* Swedish char set FNT5 */
"\377", /* Italian char set FNT6 */
"\377", /* Spanish char set FNT7 */
"\377", /* Japanese char set FNT8 */
"\377", /* Norweign char set FNT9 */
"\377", /* Danish II char set FNT10 */
"\377", /* proportional on PROP2 */
"\377", /* proportional off PROP1 */
"\377", /* proportional 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 JFY3 */
"\377", /* auto center on JFY1 */
"\0338", /* 1/8" line spacing VERP0 */
"\0336", /* 1/6" line spacing VERP1 */
"\033F", /* set form length SLPP */
"\377", /* Perf skip on 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", /* top & bottom margin set STBM */
"\377", /* left & right margin set SLRM */
"\033%C000", /* clear margins CAM */
"\377", /* set horizontal tab HTS */
"\377", /* set vertical tab VTS */
"\377", /* clear horizontal tab TBC0 */
"\033\011\015", /* clear all horizontal tabs TBC3 */
"\377", /* clear vertical tab TBC1 */
"\377", /* clear all vertical tabs TBC4 */
"\033\011\015", /* clear all h & v tabs TBCALL */
"\377", /* set default tabs TBSALL */
"\377" /* entended command EXTEND */
};
*****************************************************************************
/* dospecial.c dospecial.c dospecial.c dospecial.c dospecial.c dospecial.c */
*****************************************************************************
/* Okidata ML 92 special commands */
#include "exec/types.h"
#include "devices/printer.h"
#include "devices/prtbase.h"
extern struct PrinterData *PD ;
DoSpecial(command,OutputBuffer,vline,currentVMI,crlfFlag,Parms)
UWORD *command ; /* command number as defined in printer.h */
char OutputBuffer[] ; /* buffer into which to return converted command */
BYTE *vline ; /* value of the current line position */
BYTE *currentVMI ; /* value of the current line spacing */
BYTE *crlfFlag ; /* setting of the add <lf> after <cr> flag */
UBYTE Parms[] ; /* parameters that came with ANSI command */
{
int i, x = 0 ;
static char
initTabs[]="\033\011008,016,024,032,040,048,056,064,072\n" ;
static char
initPrinter[]="\0331\0336" ;
if (*command == aRIN ) {
/* initialize output buffer */
for (i=0; i < 4; i++)
OutputBuffer[x++] = initPrinter[i] ;
/* get preferences settings */
if ( (PD->pd_Preferences.PrintQuality) == DRAFT )
OutputBuffer[1] = '0' ;
*currentVMI = 36 ; /* initially 1/6" line spacing */
if ( (PD->pd_Preferences.PrintSpacing) == EIGHT_LPI ) {
OutputBuffer[3] = '8' ;
*currentVMI = 27 ;
}
if ( (PD->pd_Preferences.PrintPitch) == ELITE )
OutputBuffer[x++] = '\034' ;
else if ( (PD->pd_Preferences.PrintPitch) == FINE )
OutputBuffer[x++] = '\035' ;
/* what else? */
*command = aTBSALL ;
}
if (*command == aTBSALL) {
for (i=0; i < 38; i++ )
OutputBuffer[x++] = initTabs[i] ;
return(x) ;
}
/* other special functions? -> later italics in downloadable character set */
return(0) ;
}
*****************************************************************************
/* Dump.h Dump.h Dump.h Dump.h Dump.h Dump.h Dump.h Dump.h Dump.h Dump.h */
*****************************************************************************
union printerIO {
struct IOStdReq ios;
struct IODRPReq iodrp;
struct IOPrtCmdReq iopc;
};
*****************************************************************************
/* DumpRPort.c DumpRPort.c DumpRPort.c DumpRPort.c DumpRPort.c DumpRPort.c */
*****************************************************************************
#include "exec/types.h"
#include "intuition/intuition.h"
#include "devices/printer.h"
#include "Dump.h"
int DumpRPort(req, rastPort, colorMap, modes, sx, sy, sw, sh, dc, dr, s)
union printerIO *req ;
struct RastPort *rastPort;
struct ColorMap *colorMap;
ULONG modes;
UWORD sx, sy, sw, sh;
LONG dc, dr;
UWORD s;
{
req->iodrp.io_Command = PRD_DUMPRPORT;
req->iodrp.io_RastPort = rastPort;
req->iodrp.io_ColorMap = colorMap;
req->iodrp.io_Modes = modes;
req->iodrp.io_SrcX = sx;
req->iodrp.io_SrcY = sy;
req->iodrp.io_SrcWidth = sw;
req->iodrp.io_SrcHeight = sh;
req->iodrp.io_DestCols = dc;
req->iodrp.io_DestRows = dr;
req->iodrp.io_Special = s;
return(DoIO(req));
}
int OpenPrinter(request)
union printerIO *request;
{ return(OpenDevice("printer.device", 0, request, 0));
}
int ClosePrinter(request)
union printerIO *request;
{ return(CloseDevice(request));
}
*****************************************************************************
/* DumpWB.c DumpWB.c DumpWB.c DumpWB.c DumpWB.c DumpWB.c DumpWB.c DumpWB.c */
/* The following is a copy of program "printer.c" from Fred Fish's Disk #5 */
/* It links together with the object produced from "DumpRPort.c" */
*****************************************************************************
/*
*
* DISCLAIMER:
*
* This program is provided as a service to the programmer
* community to demonstrate one or more features of the Amiga
* personal computer. These code samples may be freely used
* for commercial or noncommercial purposes.
*
* Commodore Electronics, Ltd ("Commodore") makes no
* warranties, either expressed or implied, with respect
* to the program described herein, its quality, performance,
* merchantability, or fitness for any particular purpose.
* This program is provided "as is" and the entire risk
* as to its quality and performance is with the user.
* Should the program prove defective following its
* purchase, the user (and not the creator of the program,
* Commodore, their distributors or their retailers)
* assumes the entire cost of all necessary damages. In
* no event will Commodore be liable for direct, indirect,
* incidental or consequential damages resulting from any
* defect in the program even if it has been advised of the
* possibility of such damages. Some laws do not allow
* the exclusion or limitation of implied warranties or
* liabilities for incidental or consequential damages,
* so the above limitation or exclusion may not apply.
*
*/
/* printer.c - program to do a raster dump to whatever printer is specified
* by Preferences, of the Workbench Screen.
*
* Author: Rob Peck, 12/1/85
*
* This code may be freely utilized to develop programs for the Amiga
*/
#include "exec/types.h"
#include "intuition/intuition.h"
#include "devices/printer.h"
#include "Dump.h"
#define INTUITION_WONT_OPEN 1000
union printerIO *request; /* a pointer to a request block */
extern int DumpRPort();
extern int OpenPrinter();
extern int ClosePrinter();
extern struct IORequest *CreateExtIO();
extern struct Window *OpenWindow();
extern struct Port *CreatePort();
struct IntuitionBase *IntuitionBase;
struct NewWindow nw = {
0, 0, 100, 40, 0, 1, 0, 0, NULL, NULL, NULL, NULL, NULL,
0, 0, 0, 0, WBENCHSCREEN
};
main()
{
struct Window *w;
struct Screen *screen;
struct RastPort *rp;
struct ViewPort *vp;
struct ColorMap *cm;
union printerIO sizeDummy;
int modes,width,height,error;
struct Port *printerPort; /* at which to receive reply */
IntuitionBase = (struct IntuitionBase *)OpenLibrary(
"intuition.library", 0);
if (IntuitionBase == NULL) exit(INTUITION_WONT_OPEN);
w = OpenWindow(&nw);
if(w == NULL) goto cleanup1;
screen = w->WScreen; /* get screen address from window */
CloseWindow(w); /* once have screen address, no
* more need for window, close it.
*/
vp = &screen->ViewPort; /* get screen's ViewPort, from
* which the colormap will be gotten */
rp = &screen->RastPort; /* get screen's RastPort, which
* is what gets dumped to printer */
cm = vp->ColorMap; /* retrieve pointer to colormap for
* the printer dump */
modes = vp->Modes; /* retrieve the modes variable */
width = vp->DWidth; /* retrieve width to print */
height = vp->DHeight; /* retrieve height to print */
printerPort = CreatePort("my.print.port",0);
request = (union printerIO *)CreateExtIO(printerPort,
sizeof(sizeDummy));
error = OpenPrinter(request);
if(error != 0) goto cleanup2;
Delay(300); /* 300/60 = 6 seconds delay before it starts */
error = DumpRPort(
request,/* pointer to initialized request */
rp, /* rastport pointer */
cm, /* color map pointer */
modes, /* low, high res, etc (display modes)*/
0, 0, /* x and y offsets into rastport */
width,height, /* source size */
width,(height * 2), /* dest rows, columns */
SPECIAL_FULLROWS
| SPECIAL_FULLCOLS
| SPECIAL_ASPECT /* io Special value, says print
* as pixels only, direct copy */
);
ClosePrinter(request);
cleanup2:
DeleteExtIO(request, sizeof(sizeDummy));
DeletePort(printerPort);
cleanup1:
CloseLibrary(IntuitionBase);
} /* end of demo screen dump */
*****************************************************************************
* init.asm init.asm init.asm init.asm init.asm init.asm init.asm init.asm *
*****************************************************************************
**** initialization for Okidata ML 92 *****************************
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 _GfxBase
*******************************************************************
SECTION printer,DATA
_PD DC.L 0
_PED DC.L 0
_SysBase DC.L 0
_GfxBase DC.L 0
*******************************************************************
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
LEA GLName(PC),A1
MOVEQ #0,D0
CALLEXE OpenLibrary
MOVE.L D0,_GfxBase
BEQ initGLErr
MOVEQ #0,D0
pdiRts:
MOVE.L (A7)+,A6
RTS
initGLErr:
MOVEQ #-1,D0
BRA.S pdiRts
GLName:
DC.B 'graphics.library'
DC.B 0
DS.W 0
*----------------------------------------------------------------
_Expunge:
MOVE.L _GfxBase,A1
LINKEXE CloseLibrary
*----------------------------------------------------------------
_Open:
_Close:
MOVEQ #0,D0
RTS
END
*****************************************************************************
* macros.i macros.i macros.i macros.i macros.i macros.i macros.i macros.i *
*****************************************************************************
****************************************************************
* Printer Device Macros
****************************************************************
*---- external definition macros -------------------------------
XREF_EXE MACRO
XREF _LVO\1
ENDM
XREF_GFX MACRO
XREF _LVO\1
ENDM
*---- library dispatch macros ----------------------------------
CALLEXE MACRO
CALLLIB _LVO\1
ENDM
LINKEXE MACRO
LINKLIB _LVO\1,_SysBase
ENDM
LINKGFX MACRO
LINKLIB _LVO\1,_GfxBase
ENDM
*****************************************************************************
makefile makefile makefile makefile makefile makefile makefile makefile
*****************************************************************************
# works with make/pdmake from Fred Fish's disk #2
# I use the Lattice C 3.03 from a disk called "CC" and the assembler from a
# disk called "ASM". After you have modified the 3 macros at the beginning
# of the makefile you should copy the makefile to RAM: and then cd to RAM:
# This way I have the minimum disk changes with just one drive.
# It compiles and links both the Okidata ML92 printer driver and the Dump
# Workbench routines.
SOURCE = C-work:printer # redefine with the destination of your
# source directory
CCDISK = cc: # redefine with name of your cc disk
ASMDISK = ASM: # redefine with name of your asm disk
CFLAGS1 = -iRAM: -i$(CCDISK)include/ -i$(CCDISK)include/lattice/
ASMOPT = -i RAM:+$(ASMDISK)include
CC1 = $(CCDISK)c/lc1 $(CFLAGS1) RAM:
CC2 = $(CCDISK)c/lc2 RAM:
ASM = $(ASMDISK)c/Assem RAM:
OBJS1 = $(SOURCE)/data.o $(SOURCE)/dospecial.o $(SOURCE)/init.o
OBJS2 = $(SOURCE)/tag.o $(SOURCE)/render.o
OBJS = $(OBJS1) $(OBJS2) $(OBJS3) $(OBJS4) $(OBJS5)
doit : clear $(SOURCE)/Okidata_ML92 $(SOURCE)/DumpWB init
init :
assign CWD: $(SOURCE)
assign cclib: $(CCDISK)lib
assign ASMlib: $(ASMDISK)lib
copy CWD:macros.i RAM:
copy CWD:Dump.h RAM:
clear :
assign ASMlib:
assign cclib:
assign CWD:
$(SOURCE)/Okidata_ML92 : $(OBJS) $(SOURCE)/printer.link
delete RAM:macros.i
copy $(SOURCE)/printer.link to RAM:
$(CCDISK)c/alink WITH RAM:printer.link
copy RAM:Okidata_ML92 DEVS:printers
copy RAM:Okidata_ML92 CWD:
delete RAM:Okidata_ML92 RAM:printer.link
$(SOURCE)/data.o : $(SOURCE)/data.c
copy $(SOURCE)/data.c RAM:
$(CC1)data
$(CC2)data
copy RAM:data.o CWD:
delete RAM:data.?
$(SOURCE)/dospecial.o : $(SOURCE)/dospecial.c
copy $(SOURCE)/dospecial.c RAM:
$(CC1)dospecial
$(CC2)dospecial
copy RAM:dospecial.o CWD:
delete RAM:dospecial.?
$(SOURCE)/render.o : $(SOURCE)/render.c
copy $(SOURCE)/render.c RAM:
$(CC1)render
$(CC2)render
copy RAM:render.o CWD:
delete RAM:render.?
$(SOURCE)/init.o : $(SOURCE)/init.asm $(SOURCE)/macros.i
copy $(SOURCE)/init.asm RAM:
$(ASM)init.asm -o init.o $(ASMOPT)
copy RAM:init.o CWD:
delete RAM:init.\#?
$(SOURCE)/tag.o : $(SOURCE)/tag.asm
copy $(SOURCE)/tag.asm RAM:
$(ASM)tag.asm -o tag.o $(ASMOPT)
copy RAM:tag.o CWD:
delete RAM:tag.\#?
$(SOURCE)/DumpWB : $(SOURCE)/DumpWB.o $(SOURCE)/DumpRPort.o
$(CCDISK)c/alink cclib:Lstartup.obj+cwd:DumpWB.o+cwd:DumpRPort.o TO RAM:DumpWB LIBRARY cclib:lc.lib,cclib:amiga.lib
copy RAM:DumpWB CWD:
delete RAM:DumpWB
$(SOURCE)/DumpWB.o : $(SOURCE)/DumpWB.c Dump.h
copy $(SOURCE)/DumpWB.c RAM:
$(CC1)DumpWB
$(CC2)DumpWB
copy RAM:DumpWB.o CWD:
delete RAM:DumpWB.?
$(SOURCE)/DumpRPort.o : $(SOURCE)/DumpRPort.c Dump.h
copy $(SOURCE)/DumpRPort.c RAM:
$(CC1)DumpRPort
$(CC2)DumpRPort
copy RAM:DumpRPort.o CWD:
delete RAM:DumpRPort.?
*****************************************************************************
printer.link printer.link printer.link printer.link printer.link printer.link
*****************************************************************************
FROM CWD:tag.o,CWD:init.o,CWD:data.o,CWD:dospecial.o,CWD:render.o
TO RAM:Okidata_ML92
LIBRARY cclib:lc.lib,cclib:amiga.lib
*****************************************************************************
/* render.c render.c render.c render.c render.c render.c render.c render.c */
*****************************************************************************
/* Graphics render for Okidata ML 92 */
#include "exec/types.h"
#include "exec/nodes.h"
#include "exec/lists.h"
#include "exec/memory.h"
#include "devices/prtbase.h"
extern struct PrinterData *PD;
int Render(ct, x, y, status)
UBYTE ct ; /* color type = 0 for b&w printers */
UWORD x, y ; /* x and y coordinates of pixel */
/* or pc and pr print values, or special */
UBYTE status ; /* print status (0-init, 1-enter_pixel, 2-dump) */
{
static UWORD BUFSIZE;
static char *SpoolBuffer ;
char *malloc() ;
UWORD i, k; /* mics. var */
BYTE err; /* the error # */
switch(status) {
case 0 : /* allocate memory for printer buffer */
BUFSIZE = x;
PD->pd_PrintBuf = (UBYTE *)AllocMem(BUFSIZE,MEMF_PUBLIC);
SpoolBuffer = (char *)AllocMem(BUFSIZE*2+5,MEMF_PUBLIC);
/* used to actually print */
if (err=(PD->pd_PrintBuf == 0)) return(err);
(*(PD->pd_PWrite))("\30\33%C000\34",8);
/* non graphic, clear, clear left margin, 72 DPI */
return(0) ;
break ;
case 1 : /* put pixel in buffer */
PD->pd_PrintBuf[x] = PD->pd_PrintBuf[x] | (1 << (y % 7));
return(0) ; /* flag all ok */
break ;
case 2 : /* dump buffer to printer */
k = 1 ;
for (i=0 ; i < BUFSIZE; i++ ) {
SpoolBuffer[k] = PD->pd_PrintBuf[i]&127 ;
if (SpoolBuffer[k++] == '\3') /* double ETX */
SpoolBuffer[k++] = '\3' ;
}
SpoolBuffer[0] = '\03' ; /* Begin graphic mode */
SpoolBuffer[k++] = '\03' ; /* Graphic linefeed */
SpoolBuffer[k++] = '\16' ;
SpoolBuffer[k++] = '\03' ; /* End graphic mode */
SpoolBuffer[k++] = '\02' ;
(*(PD->pd_PWrite))(SpoolBuffer,k); /* write out Buffer */
return(0) ; /* flag all ok */
break ;
case 3 : /* clear and init buffer */
for (i=0; i< BUFSIZE; i++)
PD->pd_PrintBuf[i] = 0 ;
return(0) ; /* flag all ok */
break ;
case 4 : /* free print buffer memory */
(*(PD->pd_PBothReady))() ;
FreeMem(PD->pd_PrintBuf,BUFSIZE) ;
FreeMem(SpoolBuffer,BUFSIZE*2+5) ;
return(0) ;
break ;
default:
return(0) ;
}
}
*****************************************************************************
* tag.asm tag.asm tag.asm tag.asm tag.asm tag.asm tag.asm tag.asm tag.asm *
*****************************************************************************
***** printer device dependent code tag ***************************
SECTION printer
*---- Included files ----------------------------------------------
INCLUDE "exec/types.i"
INCLUDE "exec/nodes.i"
INCLUDE "exec/strings.i"
INCLUDE "devices/prtbase.i"
*---- Imported Names ----------------------------------------------
XREF _Init
XREF _Expunge
XREF _Open
XREF _Close
XREF _CommandTable
XREF _PrinterSegmentTable
XREF _DoSpecial
XREF _Render
*---- Exported Names ----------------------------------------------
XDEF _PEDData
*******************************************************************
MOVEQ #0,D0 ; show error for OpenLibrary()
RTS
DC.W 1 ; Version
DC.W 0 ; Revision
_PEDData:
DC.L printerName
DC.L _Init
DC.L _Expunge
DC.L _Open
DC.L _Close
DC.B PPC_BWGFX ; Printer Class black & white graphic
DC.B PCC_BW ; Color Class black & white
DC.B 80 ; Max Columns
DC.B 1 ; Number of Character Sets
DC.W 7 ; Number of rows
DC.L 576 ; Maximum of X dots
DC.L 0 ; Maximum of Y dots = infinite
DC.W 72 ; X Dots per inch
DC.W 72 ; Y Dots per inch
DC.L _CommandTable ; as defined in data.c
DC.L _DoSpecial ; as defined in dospecial.c
DC.L _Render ; as defined in render.c
DC.L 10 ; Timeout
printerName:
STRING <'Okidata_ML92'>
ENDlbg@gitpyr.UUCP (03/12/86)
Is it possible to get the screen dump routine out of here for use with a printer other than the Okidata? The file is too big to go through at 1200 baud and there is no good search field to help you get to the start of each embeded file! Thanks. Lee
perry@leopard.UUCP (Perry S. Kivolowitz) (03/14/86)
> Is it possible to get the screen dump routine out of here for use with > a printer other than the Okidata? The file is too big to go through at Cheer Up! The 3rd issue of amazing computing will contain a rather nice asynchronous screen image printer (SCRIMPER) for any printer capable of printing raw dot matrices. The program (runable from WB or CLI) will also be available soon on a future Fish Disk. Perry