* Printer driver skeleton for use with Double-Page IV
* Copyright 1990 Douglas N. Wheeler.  All Rights Reserved.

* NOTE: This module MUST be position-independent since no relocation is
*	performed on it.
*
*	Also, the first instruction MUST be a BRA followed immediately
*	by the longword 'DP40'.  RETURN should be at start+34.

*--------------------------------------------------------------------------
* START OF REQUIRED DATA

entry:	bra	realstart		branch to real start location

magic:	dc.l	'DP40'			magic number, must be here!
name:	dc.b	'Printer Skeleton 1.1'	20 character name of driver

* The return value is a 0 if the print was successful or a number from
* 1 to 15 which indicates the type of error that occurred.  Double-Page
* will use this number as an offset into the failure text array below and
* use the text there for the error dialog presented to the user.  The
* 'retry' list below specifies what retry action should be taken by
* Double-Page IV for a given error.

return:	dc.w	0			return value (0=no error, NZ=error)

* These two values gets filled in by Double-Page IV before the driver is
* called.  Their use is shown in the 'image_page' routine.
layoutaddr:
	dc.l	-1			address of page layout array
fontaddr:
	dc.l	-1			address of font bitmap

* These must be here, and they must be 0.
rsrvd1:	dc.w	0,0,0,0			(reserved for future expansion)
rsrvd2:	dc.w	0,0,0,0,0,0,0,0		(reserved for future expansion)

* This retry list and failure text list is from the SLM driver.

* Retry flag for each error.  0=continue with next page, 1=retry same page,
*                             2=failure - can't continue.
retry:	dc.b	2,1,0,1,0,0,1,1
	dc.b	1,1,1,1,1,1,1,1

* Text for error messages (other errors will report an UNKNOWN ERROR)
fail1:	dc.b	'INSUFFICIENT MEMORY '	text for Error 1
fail2:	dc.b	'  GENERAL ERROR 2   '	text for Error 2
fail3:	dc.b	'    TONER EMPTY     '	text for Error 3
fail4:	dc.b	' PRINTER NOT READY  '	text for Error 4
fail5:	dc.b	'    OUT OF PAPER    '	text for Error 5
fail6:	dc.b	'     DRUM EMPTY     '	text for Error 6
fail7:	dc.b	'    PAPER JAMMED    '	text for Error 7
fail8:	dc.b	'    PAPER JAMMED    '	text for Error 8
fail9:	dc.b	'    PAPER JAMMED    '	text for Error 9
fail10:	dc.b	'     COVER OPEN     '	text for Error 10
fail11:	dc.b	'  GENERAL ERROR 11  '	text for Error 11
fail12:	dc.b	'  GENERAL ERROR 12  '	text for Error 12
fail13:	dc.b	'  GENERAL ERROR 13  '	text for Error 13
fail14:	dc.b	'  GENERAL ERROR 14  '	text for Error 14
fail15:	dc.b	'  GENERAL ERROR 15  '	text for Error 15

* END OF REQUIRED DATA
*--------------------------------------------------------------------------

pageaddr:
	dc.l	-1			address of page image
	
*--------------------------------------------------------------------------
	
realstart:
	move.l	#954000,-(sp)		1 US-Letter sized page
	move.w	#$48,-(sp)		Malloc()
	trap	#1
	addq.l	#6,sp
	tst.l	d0
	beq	memfail			Oops, Malloc failed

	lea	pageaddr(pc),a3		location of page layout array variable
	move.l	d0,(a3)			save address of page buffer

	bsr	clear_page		clear page bit-map
	bsr	image_page		create bit-map from layout array
	bsr	print_page		branch to real page print routine

	lea	pageaddr(pc),a3		location of page layout array variable
	move.l	(a3),-(sp)		location of page buffer to free
	move.w	#$49,-(sp)		Mfree()
	trap	#1
	addq.l	#6,sp
	
	rts				all done	
	
memfail:
	lea	return(pc),a3		location of return variable
	move.w	#1,(a3)			insufficient memory error
	rts

*--------------------------------------------------------------------------

clear_page:
	lea	pageaddr(pc),a3		location of page image variable
	movea.l	(a3),a0			get location of page image
	move.l	#0,d2			put this in register for max speed
	move.w	#100-1,d0
.loop1:	move.w	#2385-1,d1		* 238500 longwords to clear
.loop2:	move.l	d2,(a0)+
	dbf	d1,.loop2
	dbf	d0,.loop1
	rts
	
*--------------------------------------------------------------------------

* The page layout array is an array of words, with each word representing
* one character location on the page (a word is used since using overstrike
* may result in 2 characters at a given location).
*
* The array is layed out such that the first word is the upper left character
* on the printed SHEET (not a page on that sheet).  The characters then
* proceed DOWN the page.  There are 75 columns (66 lines + borders + header +
* extra paper margins).  Each column consists of 198 words (80 characters +
* borders + margins).  Within each word, the low byte is the primary character
* at the location and the upper byte contains an overstriked character.  If
* the two characters are the same, the second should be offset slightly to
* produce a bold effect.

image_page:
	lea	layoutaddr(pc),a3	location of page layout array variable
	movea.l	(a3),a0			get location of page layout array
	lea	pageaddr(pc),a3		location of page image variable
	movea.l	(a3),a1			get location of page image
	lea	fontaddr(pc),a3		location of page font variable
	movea.l	(a3),a2			get location of font

	move.w	#0,d0			line counter
nextline:
	movea.l	a1,a3			copy of current location in page image

	move.w	#0,d1			column counter
nextcolumn:

	move.w	(a0)+,d2		next character to print
	beq	skipchar

* We can now print overlapping characters.
* Low byte is 1st char., high bytes is 2nd.
	move.w	d2,d3			duplicate
		
	andi.w	#$00ff,d3		mask to 1st character
	beq	skip1st
	movea.l	a2,a4			copy of font pointer
	lsl.w	#6,d3			times 64 (offset to character in font)
	adda.w	d3,a4			add character offset

	move.l	(a4)+,(a3)		copy character bitmap to page image
	move.l	(a4)+,300(a3)		16 longwords - unrolled for speed
	move.l	(a4)+,600(a3)
	move.l	(a4)+,900(a3)
	move.l	(a4)+,1200(a3)
	move.l	(a4)+,1500(a3)
	move.l	(a4)+,1800(a3)
	move.l	(a4)+,2100(a3)
	move.l	(a4)+,2400(a3)
	move.l	(a4)+,2700(a3)
	move.l	(a4)+,3000(a3)
	move.l	(a4)+,3300(a3)
	move.l	(a4)+,3600(a3)
	move.l	(a4)+,3900(a3)
	move.l	(a4)+,4200(a3)
	move.l	(a4)+,4500(a3)

skip1st:
	move.w	d2,d3			duplicate
	lsr.w	#8,d3			shift 2nd character into place
	andi.w	#$00ff,d3		mask to 2nd character
	beq	skip2nd			no 2nd char

	andi.w	#$00ff,d2		mask to 1st character (for comparison)
	sub.w	d3,d2			cheap compare (NZ means .ne.)
	
	movea.l	a2,a4			copy of font pointer
	lsl.w	#6,d3			times 64 (offset to character in font)
	adda.w	d3,a4			add character offset

	tst.w	d2			overstrike bold?
	beq	overstk			yes, offset by one scanline

	move.l	(a4)+,d4
	or.l	d4,(a3)
overstk:
	move.l	(a4)+,d4
	or.l	d4,300(a3)		16 longwords - unrolled for speed
	move.l	(a4)+,d4
	or.l	d4,600(a3)		16 longwords - unrolled for speed
	move.l	(a4)+,d4
	or.l	d4,900(a3)
	move.l	(a4)+,d4
	or.l	d4,1200(a3)		Note: 2nd character is offset by 1
	move.l	(a4)+,d4
	or.l	d4,1500(a3)		scanline if 1st and 2nd chars are
	move.l	(a4)+,d4
	or.l	d4,1800(a3)		the same (for overstrike bold)
	move.l	(a4)+,d4
	or.l	d4,2100(a3)
	move.l	(a4)+,d4
	or.l	d4,2400(a3)
	move.l	(a4)+,d4
	or.l	d4,2700(a3)
	move.l	(a4)+,d4
	or.l	d4,3000(a3)
	move.l	(a4)+,d4
	or.l	d4,3300(a3)
	move.l	(a4)+,d4
	or.l	d4,3600(a3)
	move.l	(a4)+,d4
	or.l	d4,3900(a3)
	move.l	(a4)+,d4
	or.l	d4,4200(a3)
	move.l	(a4)+,d4
	or.l	d4,4500(a3)

	cmp.b	d2,d3			overstrike bold?
	bne	noverstk		no, we're done

	move.l	(a4)+,d4
	or.l	d4,4800(a3)
noverstk:
skip2nd:
skipchar:
	adda.l	#4800,a3		next line in page image
	addi.w	#1,d1
	cmpi.w	#198,d1			past last line?
	bne	nextcolumn		no

	adda.l	#4,a1			next column in page image
	addi.w	#1,d0
	cmpi.w	#75,d0			past last line?
	bne	nextline		no

	rts

*--------------------------------------------------------------------------

print_page:

* The actual low-level print routine goes here, and is very device
* dependent.
*
* This routine should take the 300 dpi bitmap create by 'image_page' and
* send it to the printer.  It should also set the 'return' variable to
* reflect the success or failure of the print.
*
* This code assumes that the driver will create one big page image and
* print it all at once.  It is also possible with some printers to print
* the page in bands.  This can be accomplished by modifying image_page
* to print only a certain range of lines each time.  This has the advantage
* of using a much smaller page buffer, but is more complicated to program.

*--------------------------------------------------------------------------
