#include #include #include #include #include #include extern struct PrinterData *PD; extern struct PrinterExtendedData *PED; #define PWrite (*(PD->pd_PWrite)) /* write data to device */ #define PReady (*(PD->pd_PBothReady)) /* wait for both buffers ready */ #define LEAD 4 /* bytes to start each complete cycle */ #define EXTRA 9 /* bytes to prefix each pass of the head */ #define TAIL 2 /* bytes to end each complete cycle */ void *AllocMem(); /* these two tables wouldn't normally be bothered with but in light of * the number of times that these operations need to be performed * for each pass of the print head I thought they'd be worthwhile */ /* * this table simulates the operation (1<<(5-(y%6))) * for values of y between 0 and 23 (the number of pixels in a printer pass) * */ UBYTE bit_table[] = { 32,16,8,4,2,1, 32,16,8,4,2,1, 32,16,8,4,2,1, 32,16,8,4,2,1 }; /* this table simulates y/6 for values of y between 0 and 23 */ /* saves a long division opeation */ UBYTE div_table[] = { 0,0,0,0,0,0, 1,1,1,1,1,1, 2,2,2,2,2,2, 3,3,3,3,3,3 }; UBYTE *GfxBuffer; ULONG Render(ct,x,y,status) register UBYTE ct; register UWORD x,y; register UBYTE status; { static ULONG ROWSIZE; static ULONG COLOURSIZE; static ULONG BUFSIZE; static ULONG colours[4]; static ULONG centre; static ULONG bufptr; static UBYTE *ptr; static ULONG psize; int i,filler; int err; /* Aztec doesn't preserve a6, we need this in a printer driver */ #asm move.l a6,-(sp) #endasm err = 0; switch (status) { case 0: /* alloc memory for printer buffer */ filler = (centre) ? ((PED->ped_MaxXDots -x ) / 2 ) : 0; ROWSIZE = ((x+filler)<<2) + EXTRA; COLOURSIZE = ROWSIZE<<2; BUFSIZE = COLOURSIZE+LEAD+TAIL+1; /* plus 1 for NULL */ colours[0] = LEAD + EXTRA + filler + ROWSIZE*0; colours[1] = LEAD + EXTRA + filler + ROWSIZE*1; colours[2] = LEAD + EXTRA + filler + ROWSIZE*2; colours[3] = LEAD + EXTRA + filler + ROWSIZE*3; psize = x+filler; dbprintf("Size Data:\n"); dbprintf("\tfiller: %d\n",filler); dbprintf("\tROWSIZE: %d\n",ROWSIZE); dbprintf("\tCOLOURSIZE: %d\n",COLOURSIZE); dbprintf("\tBUFSIZE: %d\n",BUFSIZE); dbprintf("\tcolours: %d %d %d %d\n", colours[0],colours[1],colours[2],colours[3]); GfxBuffer = AllocMem(BUFSIZE*2,MEMF_PUBLIC); if (err = (GfxBuffer==0)) break; if (err = PWrite("\x1b\x1a\x49",3)) break; if (err = PWait(1,0)) break; /* set to first buffer */ bufptr = 0; break; case 1: /* render pixel */ y %= 24; /* blecch, I wanted to avoid this calculation */ i = bufptr + (x<<2) + div_table[y] + colours[3-ct]; GfxBuffer[i] |= bit_table[y]; break; case 2: /* write a buffer */ dbprintf("Writing a buffer\n"); /* BUFSIZE-1 is so that we don't send the trailing null */ if (err=PWrite(&GfxBuffer[bufptr],BUFSIZE-1)) break; bufptr = BUFSIZE-bufptr; break; case 3: /* initialize the current buffer */ dbprintf("Performing initialization\n"); ptr = &GfxBuffer[bufptr]; for (i=BUFSIZE;i--;) *ptr++ = 0; /* clear buffer */ ptr = &GfxBuffer[bufptr]; sprintf(ptr,"\x1bL07"); sprintf(ptr+LEAD ,"\r\x1bc\x1b;%04d",psize); /* c */ sprintf(ptr+LEAD+ROWSIZE ,"\r\x1bm\x1b;%04d",psize); /* m */ sprintf(ptr+LEAD+ROWSIZE*2,"\r\x1by\x1b;%04d",psize); /* y */ sprintf(ptr+LEAD+ROWSIZE*3,"\r\x1bb\x1b;%04d",psize); /* b */ sprintf(ptr+LEAD+ROWSIZE*4,"\r\n"); /* crlf + NULL */ break; case 4: /* cleanup -- release memory */ dbprintf("Print finished -- cleanup\n"); dbprintf("waiting for printer\n"); err = PReady(); dbprintf("Freeing memory\n"); FreeMem(GfxBuffer,BUFSIZE*2); dbprintf("Returning\n"); break; case 5: /* handle any special commands */ centre = x & SPECIAL_CENTER; dbprintf("special: %d %d %d %d\n",ct,x,y,status); break; default: break; } #asm move.l (sp)+,a6 #endasm return(err); }