;
; Transfer was written in assembler for speed since all bitmapped graphics
; are processed by this routine.
; 
	far	code
	far	data

   NOLIST

   include "exec/types.i"
   include "devices/printer.i"
   include "devices/prtbase.i"
   include "devices/prtgfx.i"

   LIST

PInfo    equ   8
y        equ   14
ptr      equ   16
colors   equ   20
pd_PrintShade equ pd_Preferences+pf_PrintShade

;
;  Register usage
;
; a2 - sxptr
; d2 - dvalue     d3 - width      d4 - sx        d5 - x3        d6 - x
; 

   public	_Transfer

   CSEG
_Transfer:
   link	   a5,#0
   movem.l	d2-d5/a2/a6,-(sp)
;
;  pre-compute
;  printer non-specific, MUST DO FOR EVERY PRINTER
;
   move.l   PInfo(a5),a0                  ; PInfo into A0
   moveq    #0,d6
   move.w   pi_xpos(a0),d6                ; x = PInfo->pi_xpos
   move.l   pi_ColorInt(a0),ColorInt      ; ColorInt = PInfo->pi_ColorInt
   move.l   pi_ScaleX(a0),a2              ; sxptr = PInfo->pi_ScaleX
   moveq    #0,d3
   move.w   pi_width(a0),d3               ; width = PInfo->pi_width
   sub.w    #1,d3
;
;  printer specific
;
   moveq    #0,d5
   move.w   d6,d0
   asl.w    #1,d0                         ; x * 2
   add.w    d6,d0                         ; x + x * 2
   move.w   d0,d5                         ; x3 = x + x * 2
   move.l   _PED,a0                       ; _PED into A0
   move.w   y(a5),d0                      ; get y from stack
   swap     d0
   clr.w    d0
   swap     d0
   divu.w   ped_NumRows(a0),d0            ; y % PED->ped_NumRows
   swap     d0
   move.w   d0,ymod
   and.l    #7,d0
   asl.l    #1,d0
   lea      bit_table,a0
   move.w   (a0,d0.l),bit                 ; bit = bit_table[ymod & 7]
   move.w   ymod,d0
   lsr.l    #3,d0
   add.l    d0,ptr(a5)                    ; ptr += ymod >> 3
   move.l   colors(a5),a0                 ; address of colors into A0
   lea      bptr,a1
   moveq    #3,d1
loop
   moveq    #0,d0
   move.w   (a0)+,d0                      ; colors
   add.l    ptr(a5),d0                    ; add ptr to colors
   move.l   d0,(a1)+                      ; save pointer (bptr,yptr,mptr,cptr)
   dbf      d1,loop
;
;  pre-compute threshold; are we thresholding? */
;
   moveq    #0,d0
   move.l   d0,d2
   move.l   PInfo(a5),a0
   move.w   pi_threshold(a0),d0
   beq      NotThresholding
   eor.b    #15,d0
   move.b   d0,d2                         ; dvalue = threshold ^ 15
   add.l    d5,bptr                       ; bptr += x3
;
;  pre-compute intensity values for each component
;
BWLoop1
   move.l   ColorInt,a0
   move.b   PCMBLACK(a0),Black            ; Black = ColorInt->colorByte[PCMBLACK]
   add.l    #4,ColorInt                   ; ColorInt++
   move.w   (a2)+,d4                      ; sx = *sxptr++
   sub.w    #1,d4
BWLoop2
   move.b   Black,d0
   cmp.b    d2,d0                         ; if (Black > dvalue)
   bls      BWSkip1
   move.l   bptr,a0
   bsr      orbit1                        ; *bptr |= bit
BWSkip1
   add.l    #3,bptr                       ; bptr += 3
   dbeq     d4,BWLoop2                    ; use this pixel 'sx' times
   dbeq     d3,BWLoop1                    ; do for all source pixels
   bra      done
;
;  Not thresholding, pre-compute ptr to dither matrix
;
NotThresholding
   move.w   y(a5),d0
   and.l    #3,d0
   asl.l    #2,d0                         ; (y & 3) << 2
   move.l   PInfo(a5),a0
   add.l    pi_dmatrix(a0),d0             ; PInfo->pi_dmatrix + (y & 3) << 2
   move.l   d0,dmatrix

   move.l   _PD,a0
   cmp.w    #SHADE_GREYSCALE,pd_PrintShade(a0)
   bne      COLoop1                       ; if PrintShade = GREYSCALE
   add.l    d5,bptr                       ; bptr += x3
;
;  Compute intensity values for each component
;
GSLoop1
   move.l   ColorInt,a0
   move.b   PCMBLACK(a0),Black            ; Black = ColorInt->colorByte[PCMBLACK]
   add.l    #4,ColorInt                   ; ColorInt++
   move.w   (a2)+,d4                      ; sx = *sxptr++
   sub.w    #1,d4
GSLoop2
   move.w   d6,d0
   and.l    #3,d0
   move.l   dmatrix,a0
   move.b   Black,d1
   cmp.b    (a0,d0.l),d1
   bls      GSSkip1                       ; if (Black > dmatrix[x & 3]
   move.l   bptr,a0
   bsr      orbit1                        ; *bptr |= bit
GSSkip1
   add.w    #1,d6                         ; done 1 more printer pixel
   add.l    #3,bptr                       ; bptr += 3
   dbeq     d4,GSLoop2                    ; use this pixel 'sx' times
   dbeq     d3,GSLoop1                    ; do for all source pixels
   bra      done                          ; else color
;
;  Compute intensity values for each component
;
COLoop1
   move.l   ColorInt,a0                   ; ColorInt into A0
   move.b   PCMBLACK(a0),Black            ; Black = ColorInt->colorByte[PCMBLACK]
   move.b   PCMYELLOW(a0),Yellow          ; Yellow = ColorInt->colorByte[PCMYELLOW]
   move.b   PCMMAGENTA(a0),Magenta        ; Magenta = ColorInt->colorByte[PCMMAGENTA]
   move.b   PCMCYAN(a0),Cyan              ; Cyan = ColorInt->colorByte[PCMCYAN]
   add.l    #4,ColorInt                   ; ColorInt++
   move.w   (a2)+,d4                      ; sx = *sxptr++
   sub.w    #1,d4
COLoop2
   move.w   d6,d0
   and.l    #3,d0
   move.l   dmatrix,a0
   move.b   (a0,d0.l),d2                  ; dvalue = dmatrix[x & 3]
   move.b   Black,d0
   cmp.b    d2,d0
   bls      tryyellow                     ; if (Black > dvalue)
   move.l   bptr,a0
   bra      wasblack                      ; *(bptr + x3) |= bit
tryyellow                                 ; black not rendered
   move.b   Yellow,d0
   cmp.b    d2,d0
   bls      trymagenta                    ; if (Yellow > dvalue)
   move.l   yptr,a0
   bsr      orbit                         ; *(yptr + x3) |= bit
trymagenta
   move.b   Magenta,d0
   cmp.b    d2,d0
   bls      trycyan                       ; if (Magenta > dvalue)
   move.l   mptr,a0
   bsr      orbit                         ; *(mptr + x3) |= bit
trycyan
   move.b   Cyan,d0
   cmp.b    d2,d0
   bls      nocolor                       ; if (Cyan > dvalue)
   move.l   cptr,a0
wasblack
   bsr      orbit                         ; *(cptr + x3) |= bit
nocolor
   add.w    #1,d6                         ; done 1 more printer pixel
   add.w    #3,d5                         ; x3 += 3
   dbeq     d4,COLoop2                    ; use this pixel 'sx' times
   dbeq     d3,COLoop1                    ; do for all source pixels
done
   movem.l  (sp)+,d2-d5/a2/a6
   unlk	a5
   rts

orbit
   add.l    d5,a0
orbit1
   move.b   bit+1,d0
   or.b     d0,(a0)
   rts

   DSEG
            DS    0
bit_table   DC.W  128,64,32,16,8,4,2,1
bptr        DC.L  0
yptr        DC.L  0
mptr        DC.L  0
cptr        DC.L  0
Black       DC.B  0
Yellow      DC.B  0
Magenta     DC.B  0
Cyan        DC.B  0
dmatrix     DC.L  0
color       DC.W  0
bit         DC.W  0
ymod        DC.W  0
ColorInt    DC.L  0

   public	_PED
   public	_PD

   END
