	include	"graphics/gfx.i"
	include "exec/memory.i"

	section text,code

*	Routine per la conversione ChunkyToPlanar per bitmaps fino a 8
*	bitplanes e NON interleaved, per MC68000 e MC68020
*	Copyright © 1994 by Stefano Reksten

_LVOAllocMem	EQU	-198
_LVOFreeMem		EQU	-210

*	d0: colore
*	d1: coord x
*	d2: coord y
*	a2: *bitmap
*	a3: *table

	xdef	_ChunkyToPlanar

_ChunkyToPlanar:

* salviamo d3 e d4 che useremo nella funzione.
	movem.l	d0-d5,-(sp)

* come prima cosa trasformiamo le coordinate x-y in:
* bytes dall'inizio (d2), posizione bit (d1) (d3 scratch)
	and.l	#$FFFF,d2
	asl	#2,d2
	move.l	(a3,d2),d2
	and.l	#$FFFF,d1
	move.b	d1,d3
	asr	#3,d1
	add.w	d1,d2
	moveq	#7,d1
	and.b	#%00000111,d3
	sub.b	d3,d1

	move.b	#8,d4
	sub.b	bm_Depth(a2),d4
	rol.b	d4,d0

	move.b	#$FF,d3
	bclr	d1,d3

	lea	bm_Planes(a2),a0
	lea	.DispatchTable,a1
	moveq	#0,d5
	move.b	bm_Depth(a2),d5
	lsl	#2,d5
	move.l	0(a1,d5.w),a1
	jmp	(a1)

.DispatchTable:
	dc.l	.NoPlanes,.Pl0,.Pl1,.Pl2,.Pl3,.Pl4,.Pl5,.Pl6,.Pl7

.Pl7:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	28(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.Pl6:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	24(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.Pl5:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	20(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.Pl4:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	16(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.Pl3:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	12(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.Pl2:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	8(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.Pl1:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	4(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.Pl0:
	rol.b	#1,d0
	move.b	d0,d4
	and	#%00000001,d4
	asl	d1,d4
	movea.l	(a0),a1
	adda.l	d2,a1
	and.b	d3,(a1)
	or.b	d4,(a1)

.NoPlanes:
* fine, recuperiamo i registri e torniamo.
	movem.l	(sp)+,d0-d5
	rts

	xdef	_ChunkyToPlanar68020

_ChunkyToPlanar68020:

* salviamo d3 e d4 che useremo nella funzione.
	movem.l	d0-d5,-(sp)

* come prima cosa trasformiamo le coordinate x-y in:
* bytes dall'inizio (d2), posizione bit (d1) (d3 scratch)
	move.l	(a3,d2*4),d2

	move.b	d1,d3
	asr	#3,d1
	add.l	d1,d2
	move.b	d3,d1
	and.b	#%00000111,d1

	move.b	#8,d4
	sub.b	bm_Depth(a2),d4
	rol.b	d4,d0

	move.b	#$FF,d3
	bclr	d1,d3

* mettiamo l'indirizzo dell'array dei PLANEPTR in a0
	lea	bm_Planes(a2),a0
	
	lea	.DispatchTable_020,a1
	moveq	#0,d5
	move.b	bm_Depth(a2),d5
	move.l	0(a1,d5.w*4),a1
	jmp	(a1)

.DispatchTable_020:
	dc.l	.NoPlanes_020,.Pl0_020,.Pl1_020,.Pl2_020,.Pl3_020,.Pl4_020,.Pl5_020,.Pl6_020,.Pl7_020

.Pl7_020:
	rol.b	#1,d0
	bfins	d0,([28,a0],d2.l),{d1:1}

.Pl6_020:
	rol.b	#1,d0
	bfins	d0,([24,a0],d2.l),{d1:1}

.Pl5_020:
	rol.b	#1,d0
	bfins	d0,([20,a0],d2.l),{d1:1}

.Pl4_020:
	rol.b	#1,d0
	bfins	d0,([16,a0],d2.l),{d1:1}

.Pl3_020:
	rol.b	#1,d0
	bfins	d0,([12,a0],d2.l),{d1:1}

.Pl2_020:
	rol.b	#1,d0
	bfins	d0,([8,a0],d2.l),{d1:1}

.Pl1_020:
	rol.b	#1,d0
	bfins	d0,([4,a0],d2.l),{d1:1}

.Pl0_020:
	rol.b	#1,d0
	bfins	d0,([0,a0],d2.l),{d1:1}

.NoPlanes_020:
* fine, recuperiamo i registri e torniamo.
	movem.l	(sp)+,d0-d5
	rts


*	Funzioni per creare e rilasciare la tabella di offset che serve
*	per sveltire le ChunkyToPlanar.

	xdef	_CreateCTPTable
	xdef	_FreeCTPTable

*	a2: *bitmap

_CreateCTPTable:
	movem.l	d2-d3/a6,-(sp)
	moveq	#0,d0
	move.w	bm_Rows(a2),d0
	asl	#2,d0			; prepara d0 e
	moveq	#0,d1			; d1 per AllocMem
	move.l	$4,a6
	jsr	_LVOAllocMem(a6)
	tst	d0
	beq	.notable
	move.l	d0,d3			; salva d0 (d3 scratch)
	move.l	d0,a0			; a0 = &table
	moveq	#0,d0
	move.w	bm_Rows(a2),d0
	subq	#1,d0			; prepara d0 per il ciclo
	moveq	#0,d1
	moveq	#0,d2
	move.w	bm_BytesPerRow(a2),d2
.crtloop
	move.l	d1,(a0)+
	add.l	d2,d1
	dbra	d0,.crtloop
	move.l	d3,d0			; ripristina d0
.notable
	movem.l	(sp)+,d2-d3/a6
	rts

*	a1: *table
*	a2: *bitmap

_FreeCTPTable:
	move.l	a6,-(sp)
	moveq	#0,d0
	move.w	bm_Rows(a2),d0
	asl	#2,d0
	move.l	$4,a6
	jsr	_LVOFreeMem(a6)
	move.l	(sp)+,a6
	rts



*	ChunkyToPlanarArray (solo per 68020 per ora)

*	d1: coord x
*	d2: coord y
*	d3: larghezza array
*	d4: altezza array
*	d5: bytesperrow dell'array
*	a2: *bitmap			solo lettura
*	a3: *table			solo lettura
*	a4: array di colori		modifica

	xdef	_ChunkyToPlanarArray68020

_ChunkyToPlanarArray68020:

* salviamo i registri che useremo nella funzione.
	movem.l	d0-d7/a4-a6,-(sp)
	moveq	#0,d0

* come prima cosa trasformiamo le coordinate x-y in:
* bytes dall'inizio (d2), posizione bit (d1) (d6 scratch)
	move.l	(a3,d2*4),d2
	move.b	d1,d6
	asr	#3,d1
	add.l	d1,d2
	move.b	d6,d1
	and.b	#%00000111,d1

* mettiamo l'indirizzo dell'array dei PLANEPTR in a0
	lea	bm_Planes(a2),a0

* facciamo 2 cicli: quello della larghezza interno, quello dell'altezza
* esterno. Per i contatori usiamo (ma guarda un po') proprio d3, d4
	and.l	#$0000FFFF,d5
	sub	d3,d5		; d5 = numero di colori per riga da saltare
	subq	#1,d3
	subq	#1,d4

	move.w	d3,d7		; memorizziamo la larghezza dell'array
				; da disegnare ( != larghezza totale )

	lea	.DispatchTableA_020,a1
	moveq	#0,d6
	move.b	bm_Depth(a2),d6
	move.l	0(a1,d6.w*4),a1	; a1 = indirizzo della routine
					; di disegno

	move.b	#8,d6
	sub.b	bm_Depth(a2),d6		; numero di rol da fare sul colore
					; anche se d6 era scratch non viene
 					; piu' usato.

.RowsCycle_020:
	move.l	d2,a5		; memorizziamo la posiz byte
	move.l	d1,a6		; e la posiz bit iniziale

.ColsCycle_020:
	move.b	(a4)+,d0	; d0 = colore corrente
	rol.b	d6,d0

	jmp	(a1)		; disegna il colore

.Pl7A_020:
	rol.b	#1,d0
	bfins	d0,([28,a0],d2.l),{d1:1}

.Pl6A_020:
	rol.b	#1,d0
	bfins	d0,([24,a0],d2.l),{d1:1}

.Pl5A_020:
	rol.b	#1,d0
	bfins	d0,([20,a0],d2.l),{d1:1}

.Pl4A_020:
	rol.b	#1,d0
	bfins	d0,([16,a0],d2.l),{d1:1}

.Pl3A_020:
	rol.b	#1,d0
	bfins	d0,([12,a0],d2.l),{d1:1}

.Pl2A_020:
	rol.b	#1,d0
	bfins	d0,([8,a0],d2.l),{d1:1}

.Pl1A_020:
	rol.b	#1,d0
	bfins	d0,([4,a0],d2.l),{d1:1}

.Pl0A_020:
	rol.b	#1,d0
	bfins	d0,([0,a0],d2.l),{d1:1}

.NoPlanesA_020:

* fine, recuperiamo i registri e torniamo.
	addq	#1,d1		; nuova coordinata x in posizione del bit
	and.b	#%00000111,d1
	bne.b	.GoOn_020
	addq	#1,d2
.GoOn_020
	dbra.w	d3,.ColsCycle_020

	move.w	d7,d3			; recupero contatore del ciclo
	adda.l	d5,a4			; skip dei colori
	move.l	a5,d2			; recupero bits dall'inizio
	move.l	a6,d1			; recupero bytes dall'inizio
	add.w	bm_BytesPerRow(a2),d2 	; prossima riga

	dbra.w	d4,.RowsCycle_020

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

.DispatchTableA_020
	dc.l	.NoPlanesA_020,.Pl0A_020,.Pl1A_020,.Pl2A_020
	dc.l	.Pl3A_020,.Pl4A_020,.Pl5A_020,.Pl6A_020,.Pl7A_020

	end
