;****************************************************************************
;*
;*	c2p8.asm
;*
;*	Routine di conversione chunky to planar
;*
;*
;* - Nuova gestione della conversione per schermi con pixel 1x2 o 2x2
;*   Ora scrive nello schermo destinazione un rigo si e uno no.
;*
;****************************************************************************

		opt d+,o+,l+,P=68020,DEBUG,LINE

		incdir	inc:

		include	"exec/exec_lib.i"
		include "exec/exec.i"
		include	"graphics/graphics_lib.i"
		include "hardware/custom.i"

		xdef	c2p8_init
		xdef	c2p8_go

; ---------------------------------------------------------------------

; void __asm c2p8_init (register __a0 UBYTE *chunky,	// pointer to chunky data
;			register __a1 ULONG mode,	// conversion mode
;			register __d0 ULONG signals1,	// 1 << sigbit1
;			register __d1 ULONG signals2,	// 1 << sigbit2
;			register __d2 ULONG width,      // window width
;			register __d3 ULONG height,     // window height
;			register __d4 ULONG offset,     // byte offset into plane
;			register __d5 UBYTE *buff2,	// Chip buffer width*height
;			register __d6 UBYTE *buff3,	// Chip buffer width*height
;			register __d7 ULONG scrwidth,   // screen width
;			register __a3 struct GfxBase *GfxBase);
;
; void c2p8_go(register __a0 PLANEPTR *planes, // pointer to planes
;		);
;
; -------------------------------------------------------------------
;
; Pipelined CPU+blitter 8-plane chunky to planar converter.
; Optimised for 68020/30 with fastmem.
;
; Author: Peter McGavin (e-mail peterm@maths.grace.cri.nz), 21 April 1994
; Based on James McCoull's 4-pass blitter algorithm.
;
; Modified by Conrad Sanderson (g.sanderson@ais.gu.edu.au), 4 June 1994
;
; Modified by Alberto Longo, 26 Aug 1994
;
;
; This code is public domain.
;
; algorithm:
;
; Performs first 2 passes (Fast->Chip) with the CPU (in 1 pass).
; Waits for previous QBlit() to completely finish (signals2).
; Then launches passes 3 & 4 with QBlit().
; Return immediately after launching passes 3 & 4.
; ** your task can render the next frame while the converter is still going **
; Signals via signals1 (asynchronously) after completion of pass 3.
; Signals via signals2 from CleanUp() on completion of QBlit().
;
; Approx timing for A1200+fast ram, (320x200x8):
; 	CPU pass 40-41ms
;	Asynchronous blitter passes add 62ms
;	Max framerate is 62ms/frame = 16fps
;	 occurs when fBUFFER rendering time <= 21ms (= 62ms-41ms)
;
;
;
; -------------------------------------------------------------------


;		section chunks,code

; Initialize variables

c2p8_init:
		movem.l	d2-d7/a2-a6,-(sp)

		lea	mybltnode(pc),a4

		move.l	a0,(chunky-mybltnode,a4)
		move.l	a1,(mode-mybltnode,a4)
		move.l	d0,(signals1-mybltnode,a4)
		move.l	d1,(signals2-mybltnode,a4)
		move.l	d5,(tmp_buff2-mybltnode,a4)
		move.l	d6,(tmp_buff3-mybltnode,a4)

		move.l	(4).w,a6
		move.l	a6,(sysbase-mybltnode,a4)

		move.l	(ThisTask,a6),(task-mybltnode,a4) ; save task ptr

		bsr	c2p8_waitblitter

		move.l	a1,d0
		btst	#0,d0	;Test conversion mode
		beq.s	c2p_nodoublex
		lsl.l	#1,d2	;window width*=2
c2p_nodoublex
		move.l	d2,d1
		mulu	d3,d1	;d1=# pixels

		move.l	d1,(pixels-mybltnode,a4)
		lsr.l	#1,d1
		move.l	d1,(pixels2-mybltnode,a4)
		lsr.l	#1,d1
		move.l	d1,(pixels4-mybltnode,a4)
		lsr.l	#1,d1
		move.l	d1,(pixels8-mybltnode,a4)
		lsr.l	#1,d1
		move.l	d1,(pixels16-mybltnode,a4)

		move.l	d7,d1
		lsr.l	#3,d1
		sub.l	d2,d7	;d7=screen_width - window_width
		lsr.l	#3,d7
		move.l	d7,(mod-mybltnode,a4)
		lsr.l	#1,d7
		add.l	d7,d4	;offset+=(screen_width - window_width)/16
		move.l	#200,d7
		btst	#1,d0
		beq.s	c2p_nodoubley
		lsr.l	#1,d7
		add.w	d1,(mod+2-mybltnode,a4)
		add.l	d1,d1
c2p_nodoubley
		sub.l	d3,d7
		lsr.l	#1,d7	;d7=(screen_height - window_height)>>1
		mulu	d1,d7
		add.l	d7,d4
		move.l	d4,(offset-mybltnode,a4)

		lsr.l	#4,d2
		move.l	d2,(width-mybltnode,a4)
		move.l	d3,(height-mybltnode,a4)

		subq.l	#1,d3
		mulu	(mod+2-mybltnode,a4),d3		;d3=mod*(window_height-1)
		add.l	(offset-mybltnode,a4),d3
		move.l	d3,(offset2-mybltnode,a4)

		move.l	a3,(gfxbase-mybltnode,a4)

		movem.l	(sp)+,d2-d7/a2-a6
		rts

;************************************************************************
;* Attende che il blitter abbia finito

		xdef	c2p8_waitblitter

c2p8_waitblitter
		movem.l	d0-d7/a0-a6,-(sp)

		lea	mybltnode(pc),a2	; a2->mybltnode
		move.l	(4).w,a6

		move.l	(signals1-mybltnode,a2),d0
		jsr	(_LVOWait,a6)		; Test signal1

		move.l	(signals2-mybltnode,a2),d0
		jsr	(_LVOWait,a6)		; Test signal2

		move.l	(signals1-mybltnode,a2),d0
		move.l	d0,d1
		jsr	(_LVOSetSignal,a6)	; Set signal1

		move.l	(signals2-mybltnode,a2),d0
		move.l	d0,d1
		jsr	(_LVOSetSignal,a6)	; Set signal2

		movem.l	(sp)+,d0-d7/a0-a6
		rts

;************************************************************************
;***  Start conversion
;************************************************************************

		cnop	0,8

c2p8_go:	movem.l	d2-d7/a2-a6,-(sp)

		lea	mybltnode(pc),a2

		move.l	a0,-(sp)	;Salva puntatore ai planes

; wait for previous call to c2p8 to finish pass 3

		move.l	(signals1-mybltnode,a2),d0
		move.l	(sysbase,pc),a6
		jsr	(_LVOWait,a6)			  ; signals1 in d0

		move.l	a2,a0
		move.l	(chunky-mybltnode,a0),a2

;-------------------------------------------------
;original chunky data
;0		a7a6a5a4a3a2a1a0 b7b6b5b4b3b2b1b0
;2		c7c6c5c4c3c2c1c0 d7d6d5d4d3d2d1d0
;4		e7e6e5e4e3e2e1e0 f7f6f5f4f3f2f1f0
;6		g7g6g5g4g3g2g1g0 h7h6h5h4h3h2h1h0
;8		i7i6i5i4i3i2i1i0 j7j6j5j4j3j2j1j0
;10		k7k6k5k4k3k2k1k0 l7l6l5l4l3l2l1l0
;12		m7m6m5m4m3m2m1m0 n7n6n5n4n3n2n1n0
;14		o7o6o5o4o3o2o1o0 p7p6p5p4p3p2p1p0
;16		q7q6q5q4q3q2q1q0 r7r6r5r4r3r2r1r0
;18		s7s6s5s4s3s2s1s0 t7t6t5t4t3t2t1t0
;20		u7u6u5u4u3u2u1u0 v7v6v5v4v3v2v1v0
;22		w7w6w5w4w3w2w1w0 x7x6x5x4x3x2x1x0
;24		y7y6y5y4y3y2y1y0 z7z6z5z4z3z2z1z0
;26		A7A6A5A4A3A2A1A0 B7B6B5B4B3B2B1B0
;28		C7C6C5C4C3C2C1C0 D7D6D5D4D3D2D1D0
;30		E7E6E5E4E3E2E1E0 F7F6F5F4F3F2F1F0
;-------------------------------------------------

		btst	#0,(mode-mybltnode+3,a0)	;test conversion mode
		bne	c2p_doublew

		move.l	(pixels4-mybltnode,a0),d0
		move.l	(tmp_buff2,pc),a0

		lea	(a0,d0.l),a1	; a1 -> buff2+pixels/4
		lea	(a1,d0.l),a4	; a4 -> buff2+pixels/2
		lea	(a4,d0.l),a5	; a5 -> buff2+3*pixels/4

		move.l	a1,a3		; a3 = for finish test

		move.l	#$0f0f0f0f,d7	; constant
		move.l	#$00ff00ff,d6	; constant

		bra.s	c2p_loop

		cnop	0,8

; convert 32 pixels (passes 1 and 2 combined)

c2p_loop:	

;First 16 pixels
		move.l	(a2)+,d0	; AaBbCcDd
		move.l	(a2)+,d1	; EeFfGgHh
		move.l	(a2)+,d2	; IiJjKkLl
		move.l	(a2)+,d3	; MmNnOoPp

		move.l	d0,d4		; AaBbCcDd
		and.l	d6,d4		; ..Bb..Dd
		eor.l	d4,d0		; Aa..Cc..
		lsl.l	#8,d4		; Bb..Dd..

		move.l	d2,d5		; IiJjKkLl
		and.l	d6,d5		; ..Jj..Ll
		eor.l	d5,d2		; Ii..Kk..
		lsr.l	#8,d2		; ..Ii..Kk

		or.l	d2,d0		; AaIiCcKk
		or.l	d5,d4		; BbJjDdLl

		move.l	d1,d2		; EeFfGgHh
		and.l	d6,d2		; ..Ff..Hh
		eor.l	d2,d1		; Ee..Gg..
		lsl.l	#8,d2		; Ff..Hh..

		move.l	d3,d5		; MmNnOoPp
		and.l	d6,d5		; ..Nn..Pp
		eor.l	d5,d3		; Mm..Oo..
		lsr.l	#8,d3		; ..Mm..Oo

		or.l	d3,d1		; EeMmGgOo
		or.l	d5,d2		; FfNnHhPp

		move.l	d0,d3		; AaIiCcKk
		and.l	d7,d3		; .a.i.c.k
		eor.l	d3,d0		; A.I.C.K.
		lsl.l	#4,d3		; a.i.c.k.

		move.l	d1,d5		; EeMmGgOo
		and.l	d7,d5		; .e.m.g.o

		or.l	d5,d3		; aeimcgko
		move.l	d3,(a4)+

		eor.l	d5,d1		; E.M.G.O.
		lsr.l	#4,d1		; .E.M.G.O

		or.l	d1,d0		; AEIMCGKO
		move.l	d0,(a0)+

		move.l	d4,d1		; BbJjDdLl
		and.l	d7,d1		; .b.j.d.l
		eor.l	d1,d4		; B.J.D.L.
		lsl.l	#4,d1		; b.j.d.l.

		move.l	d2,d5		; FfNnHhPp
		and.l	d7,d5		; .f.n.h.p

		or.l	d5,d1		; bfjndhlp
		move.l	d1,(a5)+

		eor.l	d5,d2		; F.N.H.P.
		lsr.l	#4,d2		; .F.N.H.P

		or.l	d2,d4		; BFJNDHLP
		move.l	d4,(a1)+

;Last 16 pixels

		move.l	(a2)+,d0	; AaBbCcDd
		move.l	(a2)+,d1	; EeFfGgHh
		move.l	(a2)+,d2	; IiJjKkLl
		move.l	(a2)+,d3	; MmNnOoPp

		move.l	d0,d4		; AaBbCcDd
		and.l	d6,d4		; ..Bb..Dd
		eor.l	d4,d0		; Aa..Cc..
		lsl.l	#8,d4		; Bb..Dd..

		move.l	d2,d5		; IiJjKkLl
		and.l	d6,d5		; ..Jj..Ll
		eor.l	d5,d2		; Ii..Kk..
		lsr.l	#8,d2		; ..Ii..Kk

		or.l	d2,d0		; AaIiCcKk
		or.l	d5,d4		; BbJjDdLl

		move.l	d1,d2		; EeFfGgHh
		and.l	d6,d2		; ..Ff..Hh
		eor.l	d2,d1		; Ee..Gg..
		lsl.l	#8,d2		; Ff..Hh..

		move.l	d3,d5		; MmNnOoPp
		and.l	d6,d5		; ..Nn..Pp
		eor.l	d5,d3		; Mm..Oo..
		lsr.l	#8,d3		; ..Mm..Oo

		or.l	d3,d1		; EeMmGgOo
		or.l	d5,d2		; FfNnHhPp

		move.l	d0,d3		; AaIiCcKk
		and.l	d7,d3		; .a.i.c.k
		eor.l	d3,d0		; A.I.C.K.
		lsl.l	#4,d3		; a.i.c.k.

		move.l	d1,d5		; EeMmGgOo
		and.l	d7,d5		; .e.m.g.o

		or.l	d5,d3		; aeimcgko
		move.l	d3,(a4)+

		eor.l	d5,d1		; E.M.G.O.
		lsr.l	#4,d1		; .E.M.G.O

		or.l	d1,d0		; AEIMCGKO
		move.l	d0,(a0)+

		move.l	d4,d1		; BbJjDdLl
		and.l	d7,d1		; .b.j.d.l
		eor.l	d1,d4		; B.J.D.L.
		lsl.l	#4,d1		; b.j.d.l.

		move.l	d2,d5		; FfNnHhPp
		and.l	d7,d5		; .f.n.h.p

		or.l	d5,d1		; bfjndhlp
		move.l	d1,(a5)+

		eor.l	d5,d2		; F.N.H.P.
		lsr.l	#4,d2		; .F.N.H.P

		or.l	d2,d4		; BFJNDHLP
		move.l	d4,(a1)+

go_end1		cmpa.l	a3,a0		;Test finish
		blt	c2p_loop



; wait until previous QBlit() has completely finished (signals2)
; then start the blitter in the background for passes 3 & 4

done:		lea	mybltnode(pc),a2	; a2->mybltnode
		move.l	sysbase(pc),a6		; a6->SysBase
		move.l	(signals2-mybltnode,a2),d0
		jsr	(_LVOWait,a6)

		move.l	(sp)+,(planes-mybltnode,a2)

		move.l	a2,a1
		move.l	(gfxbase-mybltnode,a2),a6
		jsr	(_LVOQBlit,a6)

		movem.l	(sp)+,d2-d7/a2-a6
		rts


;----------------------------------------------------------------------------
;*** Double pixel width

c2p_doublew
		move.l	(pixels8-mybltnode,a0),d6	; loop count
		lsr.l	#1,d6

		move.l	(pixels4-mybltnode,a0),d0
		move.l	(tmp_buff2,pc),a0

		lea	(a0,d0.l),a1	; a1 -> buff2+pixels/4
		lea	(a1,d0.l),a4	; a4 -> buff2+pixels/2
		lea	(a4,d0.l),a5	; a5 -> buff2+3*pixels/4

		move.l	#$f0f00f0f,d5	;d5=mask

		bra.s	go_end2


		cnop	0,8

; convert 8 pixels (passes 1 and 2 combined) into 16 pixels

c2p_loop2
		move.l	(a2)+,d0	;d0=AaBbCcDd
		move.l	(a2)+,d1	;d1=EeFfGgHh

		ror.w	#4,d0		;d0=AaBbdCcD
		move.l	d0,d2
		and.l	d5,d0		;d0=A.B..C.D
		eor.l	d0,d2		;d2=.a.bd.c.

		ror.w	#4,d1		;d1=EeFfhGgH
		move.l	d1,d3
		and.l	d5,d1		;d1=E.F..G.H
		eor.l	d1,d3		;d3=.e.fh.g.


		move.l	d0,d4
		swap	d0		;d0=.C.DA.B.
		or.l	d4,d0		;d0=ACBDACBD
		clr.b	d0		;d0=ACBDAC..
		swap	d0		;d0=AC..ACBD
		lsl.w	#8,d0		;d0=AC..BD..

		move.l	d1,d4
		swap	d1		;d1=.G.HE.F.
		or.l	d4,d1		;d1=EGFHEGFH
		lsr.l	#8,d1		;d1=..EGFHEG
		lsr.w	#8,d1		;d1=..EG..FH

		or.l	d1,d0		;d0=ACEGBDFH
		move.l	d0,(a0)+

		lsl.l	#4,d2		;d2=a.bd.c..
		move.l	d2,d4
		swap	d2		;d2=.c..a.bd
		or.l	d4,d2		;d2=acbdacbd
		clr.b	d2		;d2=acbdac..
		swap	d2		;d2=ac..acbd
		lsl.w	#8,d2		;d2=ac..bd..

		move.l	d0,(a1)+

		lsl.l	#4,d3		;d3=e.fh.g..
		move.l	d3,d4
		swap	d3		;d3=.g..e.fh
		or.l	d4,d3		;d3=egfhegfh
		lsr.l	#8,d3		;d3=..egfheg
		lsr.w	#8,d3		;d3=..eg..fh

		or.l	d3,d2		;d2=acegbdfh

		move.l	d2,(a4)+
		move.l	d2,(a5)+

go_end2		dbra	d6,c2p_loop2

		bra	done

;----------------------------------------------------------------------------



; If we get to here then no difference was found.
; Signal the task (signals1) and return.
;
;		cnop 0,4
;
;done2:		lea	mybltnode(pc),a2
;		move.l	(signals1-mybltnode,a2),d0
;		move.l	d0,d1
;		move.l	sysbase(pc),a6	; a6->SysBase
;		jsr	(_LVOSetSignal,a6)
;
;ret:		movem.l	(sp)+,d2-d7/a2-a6
;		rts

;-----------------------------------------------------------------------------
; QBlit functions (called asynchronously)

;-------------------------------------------------
;buff2 after pass 2
;0		a7a6a5a4e7e6e5e4 i7i6i5i4m7m6m5m4
;2		c7c6c5c4g7g6g5g4 k7k6k5k4o7o6o5o4
;4		q7q6q5q4u7u6u5u4 y7y6y5y4C7C6C5C4
;6		s7s6s5s4w7w6w5w4 A7A6A5A4E7E6E5E4
;
;Pixels/4+0	b7b6b5b4f7f6f5f4 j7j6j5j4n7n6n5n4
;Pixels/4+2	d7d6d5d4h7h6h5h4 l7l6l5l4p7p6p5p4
;Pixels/4+4	r7r6r5r4v7v6v5v4 z7z6z5z4D7D6D5D4
;Pixels/4+6	t7t6t5t4x7x6x5x4 B7B6B5B4F7F6F5F4
;
;Pixels/2+0	a3a2a1a0e3e2e1e0 i3i2i1i0m3m2m1m0
;Pixels/2+2	c3c2c1c0g3g2g1g0 k3k2k1k0o3o2o1o0
;Pixels/2+4	q3q2q1q0u3u2u1u0 y3y2y1y0C3C2C1C0
;Pixels/2+6	s3s2s1s0w3w2w1w0 A3A2A1A0E3E2E1E0
;
;3*Pixels/4+0	b3b2b1b0f3f2f1f0 j3j2j1j0n3n2n1n0	
;3*Pixels/4+2	d3d2d1d0h3h2h1h0 l3l2l1l0p3p2p1p0
;3*Pixels/4+4	r3r2r1r0v3v2v1v0 z3z2z1z0D3D2D1D0
;3*Pixels/4+6	t3t2t1t0x3x2x1x0 B3B2B1B0F3F2F1F0
;-------------------------------------------------

;Pass 3, subpass 1
;	apt		Buff2
;	bpt		Buff2+2
;	dpt		Buff3
;	amod		2
;	bmod		2
;	dmod		0
;	cdat		$cccc
;	sizv		Pixels/4
;	sizh		1 word
;	con		D=AC+(B>>2)~C, ascending

		cnop 0,4

blit31:		moveq	#-1,d0
		move.l	d0,(bltafwm,a0)
		move.w	#0,(bltdmod,a0)

		move.l	(tmp_buff2,pc),d1
		move.l	d1,(bltapt,a0)

		addq.l	#2,d1				; buff2+2
		move.l	d1,(bltbpt,a0)


		move.l	(tmp_buff3,pc),(bltdpt,a0)
		move.w	#2,(bltamod,a0)			; 2
		move.w	#2,(bltbmod,a0)			; 2
		move.w	(pixels4+2-mybltnode,a1),(bltsizv,a0)	; pixels/4
		move.w	#$cccc,(bltcdat,a0)
		move.l	#$0DE42000,(bltcon0,a0)	; D=AC+(B>>2)~C
		move.w	#1,(bltsizh,a0)		;do blit
		lea	(blit32,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		rts

;Pass 3, subpass 2
;	apt		Buff2+Pixels-2-2
;	bpt		Buff2+Pixels-2
;	dpt		Buff3+Pixels-2
;	amod		2
;	bmod		2
;	dmod		0
;	cdat		$cccc
;	sizv		Pixels/4
;	sizh		1 word
;	con		D=(A<<2)C+B~C, descending

		cnop 0,4

blit32:		move.l	(tmp_buff2,pc),d0
		add.l	(pixels-mybltnode,a1),d0
		subq.l	#2+2,d0
		move.l	d0,(bltapt,a0)		; buff2+pixels-2-2
		addq.l	#2,d0
		move.l	d0,(bltbpt,a0)		; buff2+pixels-2

		sub.l	(tmp_buff2,pc),d0
		add.l	(tmp_buff3,pc),d0

		move.l	d0,(bltdpt,a0)		; buff3+pixels-2
		move.l	#$2DE40002,(bltcon0,a0)	; D=(A<<2)C+B~C, desc.
		move.w	#1,(bltsizh,a0)		;do blit
		lea	(blit47,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		rts

;-------------------------------------------------
;buff3 after pass 3
;0		a7a6c7c6e7e6g7g6 i7i6k7k6m7m6o7o6
;2		q7q6s7s6u7u6w7w6 y7y6A7A6C7C6E7E6
;
;Pixels/8+0	b7b6d7d6f7f6h7h6 j7j6l7l6n7n6p7p6
;Pixels/8+2	r7r6t7t6v7v6x7x6 z7z6B7B6D7D6F7F6
;
;Pixels/4+0	a3a2c3c2e3e2g3g2 i3i2k3k2m3m2o3o2
;Pixels/4+2	q3q2s3s2u3u2w3w2 y3y2A3A2C3C2E3E2
;
;3*Pixels/8+0	b3b2d3d2f3f2h3h2 j3j2l3l2n3n2p3p2
;3*Pixels/8+2	r3r2t3t2v3v2x3x2 z3z2B3B2D3D2F3F2
;
;Pixels/2+0	a5a4c5c4e5e4g5g4 i5i4k5k4m5m4o5o4
;Pixels/2+2	q5q4s5s4u5u4w5w4 y5y4A5A4C5C4E5E4
;
;5*Pixels/8+0	b5b4d5d4f5f4h5h4 j5j4l5l4n5n4p5p4
;5*Pixels/8+2	r5r4t5t4v5v4x5x4 z5z4B5B4D5D4F5F4
;
;3*Pixels/4+0	a1a0c1c0e1e0g1g0 i1i0k1k0m1m0o1o0
;3*Pixels/4+2	q1q0s1s0u1u0w1w0 y1y0A1A0C1C0E1E0
;
;7*Pixels/8+0	b1b0d1d0f1f0h1h0 j1j0l1l0n1n0p1p0
;7*Pixels/8+2	r1r0t1t0v1v0x1x0 z1z0B1B0D1D0F1F0
;-------------------------------------------------

;Pass 4, plane 7
;	apt		Buff3+0*pixels/8
;	bpt		Buff3+1*pixels/8
;	dpt		Plane7+offset
;	amod		0
;	bmod		0
;	dmod		mod
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=AC+(B>>1)~C, ascending

		cnop 0,4

blit47:		movem.l	a2,-(sp)
		move.l	(tmp_buff3,pc),d0
		move.l	d0,(bltapt,a0)		; buff3+0*pixels/8
		add.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltbpt,a0)		; buff3+1*pixels/8
		move.l	(planes-mybltnode,a1),a2
		move.l	(7*4,a2),d0
		add.l	(offset-mybltnode,a1),d0
		move.l	d0,(bltdpt,a0)		; Plane7+offset
		move.w	#0,(bltamod,a0)
		move.w	#0,(bltbmod,a0)
		move.w	(mod+2-mybltnode,a1),(bltdmod,a0)
		move.w	(height+2-mybltnode,a1),(bltsizv,a0)	; height
		move.w	#$aaaa,(bltcdat,a0)
		move.l	#$0DE41000,(bltcon0,a0)	; D=AC+(B>>1)~C
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 7

		movem.l	a1/a6,-(sp)
		move.l	(signals1-mybltnode,a1),d0
		move.l	(task-mybltnode,a1),a1
		move.l	sysbase(pc),a6		; a6->SysBase
		jsr	(_LVOSignal,a6)		; signal pass 3 has finished
		movem.l	(sp)+,a1/a6

		lea	(blit43,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		movem.l	(sp)+,a2
		rts

;-------------------------------------------------
;Plane7		a7b7c7d7e7f7g7h7 i7j7k7l7m7n7o7p7
;Plane7+2	q7r7s7t7u7v7w7x7 y7z7A7B7C7D7E7F7
;-------------------------------------------------

;Pass 4, plane 3
;	apt		buff3+2*pixels/8
;	bpt		buff3+3*pixels/8
;	dpt		Plane3+offset
;	amod		0
;	bmod		0
;	dmod		mod
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=AC+(B>>1)~C, ascending

		cnop 0,4

blit43:		move.l	a2,d1			; preserve a2
		move.l	(tmp_buff3,pc),d0
		add.l	(pixels4-mybltnode,a1),d0
		move.l	d0,(bltapt,a0)		; buff3+2*pixels/8
		add.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltbpt,a0)		; buff3+3*pixels/8
		move.l	(planes-mybltnode,a1),a2
		move.l	(3*4,a2),d0
		add.l	(offset-mybltnode,a1),d0
		move.l	d0,(bltdpt,a0)		; Plane3+offset
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 3
		lea	(blit45,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		move.l	d1,a2			; restore a2
		rts

;-------------------------------------------------
;Plane3		a3b3c3d3e3f3g3h3 i3j3k3l3m3n3o3p3
;Plane3+2	q3r3s3t3u3v3w3x3 y3z3A3B3C3D3E3F3
;-------------------------------------------------

;Pass 4, plane 5
;	apt		buff3+4*pixels/8
;	bpt		buff3+5*pixels/8
;	dpt		Plane5+offset
;	amod		0
;	bmod		0
;	dmod		mod
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=AC+(B>>1)~C, ascending

		cnop 0,4

blit45:		move.l	a2,d1			; preserve a2
		move.l	(tmp_buff3,pc),d0
		add.l	(pixels2-mybltnode,a1),d0
		move.l	d0,(bltapt,a0)		; buff3+4*pixels/8
		add.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltbpt,a0)		; buff3+5*pixels/8
		move.l	(planes-mybltnode,a1),a2
		move.l	(5*4,a2),d0
		add.l	(offset-mybltnode,a1),d0
		move.l	d0,(bltdpt,a0)		; Plane5+offset
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 5
		lea	(blit41,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		move.l	d1,a2			; restore a2
		rts

;-------------------------------------------------
;Plane5		a5b5c5d5e5f5g5h5 i5j5k5l5m5n5o5p5
;Plane5+2	q5r5s5t5u5v5w5x5 y5z5A5B5C5D5E5F5
;-------------------------------------------------

;Pass 4, plane 1
;	apt		buff3+6*pixels/8
;	bpt		buff3+7*pixels/8
;	dpt		Plane1+offset
;	amod		0
;	bmod		0
;	dmod		mode
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=AC+(B>>1)~C, ascending

		cnop 0,4

blit41:		move.l	a2,d1			; preserve a2
		move.l	(tmp_buff3,pc),d0
		add.l	(pixels4-mybltnode,a1),d0
		add.l	(pixels2-mybltnode,a1),d0
		move.l	d0,(bltapt,a0)		; buff3+6*pixels/8
		add.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltbpt,a0)		; buff3+7*pixels/8
		move.l	(planes-mybltnode,a1),a2
		move.l	(1*4,a2),d0
		add.l	(offset-mybltnode,a1),d0
		move.l	d0,(bltdpt,a0)		; Plane1+offset
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 1
		lea	(blit46,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		move.l	d1,a2			; restore a2
		rts

;-------------------------------------------------
;Plane1		a1b1c1d1e1f1g1h1 i1j1k1l1m1n1o1p1
;Plane1+2	q1r1s1t1u1v1w1x1 y1z1A1B1C1D1E1F1
;-------------------------------------------------

;Pass 4, plane 6
;	apt		buff3+1*pixels/8-2
;	bpt		buff3+2*pixels/8-2
;	dpt		Plane6+plsiz-2+offset2
;	amod		0
;	bmod		0
;	dmod		mod
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=(A<<1)C+B~C, descending

		cnop 0,4

blit46:		move.l	a2,d1			; preserve a2
		move.l	(tmp_buff3,pc),d0
		add.l	(pixels8-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltapt,a0)		; buff3+1*pixels/8-2
		add.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltbpt,a0)		; buff3+2*pixels/8-2
		move.l	(planes-mybltnode,a1),a2
		move.l	(6*4,a2),d0
		add.l	(offset2-mybltnode,a1),d0
		add.l	(pixels8-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltdpt,a0)		; Plane6+offset+plsiz-2
		move.l	#$1DE40002,(bltcon0,a0)	; D=(A<<1)C+B~C, desc.
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 6
		lea	(blit42,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		move.l	d1,a2			; restore a2
		rts

;-------------------------------------------------
;Plane6		a6b6c6d6e6f6g6h6 i6j6k6l6m6n6o6p6
;Plane6+2	q6r6s6t6u6v6w6x6 y6z6A6B6C6D6E6F6
;-------------------------------------------------

;Pass 4, plane 2
;	apt		buff3+3*pixels/8-2
;	bpt		buff3+4*pixels/8-2
;	dpt		Plane2+plsiz-2+offset2
;	amod		0
;	bmod		0
;	dmod		mod
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=(A<<1)C+B~C, descending

		cnop 0,4

blit42:		move.l	a2,d1			; preserve a2
		move.l	(tmp_buff3,pc),d0
		add.l	(pixels2-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltbpt,a0)		; buff3+4*pixels/8-2
		sub.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltapt,a0)		; buff3+3*pixels/8-2
		move.l	(planes-mybltnode,a1),a2
		move.l	(2*4,a2),d0
		add.l	(offset2-mybltnode,a1),d0
		add.l	(pixels8-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltdpt,a0)		; Plane2+offset+plsiz-2
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 2
		lea	(blit44,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		move.l	d1,a2			; restore a2
		rts

;-------------------------------------------------
;Plane2		a2b2c2d2e2f2g2h2 i2j2k2l2m2n2o2p2
;Plane2+2	q2r2s2t2u2v2w2x2 y2z2A2B2C2D2E2F2
;-------------------------------------------------

;Pass 4, plane 4
;	apt		buff3+5*pixels/8-2
;	bpt		buff3+6*pixels/8-2
;	dpt		Plane4+plsiz-2+offset2
;	amod		0
;	bmod		0
;	dmod		mod
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=(A<<1)C+B~C, descending

		cnop 0,4

blit44:		move.l	a2,d1			; preserve a2
		move.l	(tmp_buff3,pc),d0
		add.l	(pixels2-mybltnode,a1),d0
		add.l	(pixels4-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltbpt,a0)		; buff3+6*pixels/8-2
		sub.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltapt,a0)		; buff3+5*pixels/8-2
		move.l	(planes-mybltnode,a1),a2
		move.l	(4*4,a2),d0
		add.l	(offset2-mybltnode,a1),d0
		add.l	(pixels8-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltdpt,a0)		; Plane4+offset+plsiz-2
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 4
		lea	(blit40,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		move.l	d1,a2			; restore a2
		rts

;-------------------------------------------------
;Plane4		a4b4c4d4e4f4g4h4 i4j4k4l4m4n4o4p4
;Plane4+2	q4r4s4t4u4v4w4x4 y4z4A4B4C4D4E4F4
;-------------------------------------------------

;Pass 4, plane 0
;	apt		buff3+7*pixels/8-2
;	bpt		buff3+8*pixels/8-2
;	dpt		Plane0+plsiz-2+offset2
;	amod		0
;	bmod		0
;	dmod		mod
;	cdat		$aaaa
;	sizv		height
;	sizh		width
;	con		D=(A<<1)C+B~C, descending

		cnop 0,4

blit40:		move.l	a2,d1			; preserve a2
		move.l	(tmp_buff3,pc),d0
		add.l	(pixels-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltbpt,a0)		; buff3+8*pixels/8-2
		sub.l	(pixels8-mybltnode,a1),d0
		move.l	d0,(bltapt,a0)		; buff3+7*pixels/8-2
		move.l	(planes-mybltnode,a1),a2
		move.l	(a2),d0
		add.l	(offset2-mybltnode,a1),d0
		add.l	(pixels8-mybltnode,a1),d0
		subq.l	#2,d0
		move.l	d0,(bltdpt,a0)		; Plane0+offset+plsiz-2
		move.w	(width+2-mybltnode,a1),(bltsizh,a0)	;plane 0
		lea	(blit31,pc),a0
		move.l	a0,(qblitfunc-mybltnode,a1)
		move.l	d1,a2			; restore a2
		moveq	#0,d0			; set Z flag
		rts

;-------------------------------------------------
;Plane0		a0b0c0d0e0f0g0h0 i0j0k0l0m0n0o0p0
;Plane0+2	q0r0s0t0u0v0w0x0 y0z0A0B0C0D0E0F0
;-------------------------------------------------

		cnop 0,4

qblitcleanup:	movem.l	a2/a6,-(sp)
		lea	mybltnode(pc),a2
		move.l	(task-mybltnode,a2),a1	; signal QBlit() has finished
		move.l	(signals2-mybltnode,a2),d0
		move.l	sysbase(pc),a6
		jsr	(_LVOSignal,a6)		; may be called from interrupts
		movem.l	(sp)+,a2/a6
		rts


; ----------------------------- data --------------------------------------
; not in a seperate section since some variables can be referred via (pc)

		cnop 0,4		; align to 32 bits

cleanup		equ	$40

mybltnode:	dc.l	0		; next bltnode
qblitfunc:	dc.l	blit31		; ptr to qblitfunc()
		dc.b	cleanup		; stat
		dc.b	0		; filler
		dc.w	0		; blitsize
		dc.w	0		; beamsync
		dc.l	qblitcleanup	; ptr to qblitcleanup()

		cnop 0,4

	xdef	offset

mode		dc.l	0		: conversion mode: 0=normal; 1=double width
chunky:		dc.l	0		; ptr to original chunky data
planes:		dc.l	0		; ptr to list of output plane ptrs
width		dc.l	0		; width/16
height		dc.l	0		; height
mod		dc.l	0		: d channel module
pixels:		dc.l	0		; width*height
pixels2:	dc.l	0		; width*height/2
pixels4:	dc.l	0		; width*height/4
pixels8:	dc.l	0		; width*height/8
pixels16:	dc.l	0		; width*height/16
offset:		dc.l	0		; byte offset into plane
offset2:	dc.l	0		; byte offset into plane for descending blitting
tmp_buff2:	dc.l	0		; pointer to chip buffer
tmp_buff3:	dc.l	0		; pointer to chip buffer
task:		dc.l	0		; ptr to this task
signals1:	dc.l	0		; signals to Signal() after pass 3
signals2:	dc.l	0		; signals to Signal() at cleanup
gfxbase:	dc.l	0		; GfxBase
sysbase:	dc.l	0		; ExecBase

		end

