
	include "exec/types.i"
	include "exec/memory.i"
	include "exec/funcdef.i"
	include "exec/exec_lib.i"
	include "graphics/gfx.i"

	XDEF    _c2p8
	XDEF    @c2p8
	XDEF    _c2p8_reloc
	XDEF    @c2p8_reloc
	XDEF    _c2p8_deinit
	XDEF    @c2p8_deinit

		section	text,code
*
*   c2p8_040_amlaukka.s - chunky to planar for bytes
*   by Aki Laukkanen <amlaukka@cc.helsinki.fi>
*
*   This file is public domain.
*

patch	macro
;;	move.l	d1,(\1-_c2p8start+4,a0)	; This fails because of bug in PhxAss
	movea.l	#\1-_c2p8start,a1		; so try this way instead.
	move.l	d1,4(a0,a1.l)
	endm

	cnop    0,16
;
; void __asm *c2p8_reloc(register __a0 struct BitMap *bitmap);
;

_c2p8_reloc
@c2p8_reloc
	movem.l d2-d7/a2-a6,-(sp)

	move.l	a0,-(sp)
	move.l  #_c2p8_end-_c2p8start,d0
	move.l  #MEMF_FAST,d1
	move.l	4.w,a6
	jsr     _LVOAllocVec(a6)
	move.l	(sp)+,a3
	tst.l   d0
	beq     .fail
	move.l  d0,a0                   ; FIXME: align by cache line
					; size and make changes to
					; the c2p too.
	lea     _c2p8start,a1
	move.w  #_c2p8_end-_c2p8start-1,d1
.loop
	move.b  (a1)+,(a0)+
	dbf     d1,.loop

	move.l	bm_Planes(a3),d2

	move.l  d0,a0
	move.l  bm_Planes+4(a3),d1
	sub.l   d2,d1
	patch	c2p8_p1_1
	patch	c2p8_p1_2
	move.l  bm_Planes+8(a3),d1
	sub.l   d2,d1
	patch	c2p8_p2_1
	patch	c2p8_p2_2
	move.l  bm_Planes+12(a3),d1
	sub.l   d2,d1
	patch	c2p8_p3_1
	patch	c2p8_p3_2
	move.l  bm_Planes+16(a3),d1
	sub.l   d2,d1
	patch	c2p8_p4_1
	patch	c2p8_p4_2
	move.l  bm_Planes+20(a3),d1
	sub.l   d2,d1
	patch	c2p8_p5_1
	patch	c2p8_p5_2
	move.l  bm_Planes+24(a3),d1
	sub.l   d2,d1
	patch	c2p8_p6_1
	patch	c2p8_p6_2
	move.l  bm_Planes+28(a3),d1
	sub.l   d2,d1
	patch	c2p8_p7_1
	patch	c2p8_p7_2

	move.l	d0,-(sp)
	move.l	4.w,a6
	jsr     _LVOCacheClearU(a6)
	move.l	(sp)+,d0

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

	cnop    0,16

*
*   void __asm c2p8_deinit(register __a0 void *c2p);
*

_c2p8_deinit
@c2p8_deinit
	movem.l	d2-d7/a2-a6,-(sp)
	move.l	a0,d0
	beq.b	.s0
	move.l	4.w,a6
	move.l  a0,a1
;	jsr     _LVOFreeVec(a6)
.s0	movem.l	(sp)+,d2-d7/a2-a6
	rts

;void __asm c2p8(register __a0 void *c2p,
;		 register __a1 struct BitMap *bmp,
;		 register __a2 UBYTE *chunky,
;		 register __d0 ULONG size);

_c2p8
@c2p8
	movem.l d2-d7/a2-a6,-(sp)

	move.l	a0,d2
	beq.b	.no
	move.l	a1,d2
	beq.b	.no
	move.l	a2,d2
	beq.b	.no
	tst.l	d0
	beq.b	.no

	move.l	a2,a6
	move.l	a2,a3
	add.l	d0,a3
	move.l	bm_Planes(a1),a2

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

_c2p8start:
c2p8_start
; a6 - chunky
; a2 - bitplanes
; a3 - chunky end

	move.l  (a6)+,d0
	move.l  (a6)+,d1
	move.l  (a6)+,d2
	move.l  (a6)+,d3
	move.l  (a6)+,d4
	move.l  (a6)+,d5
	move.l  (a6)+,d6
	move.l  (a6)+,a0

; 16x4: (d0,d4),(d2,d6),(d1,d5)
; 2x4: (d0,d4),(d2,d6),(d1,d5)
; 16x4: (d3,d7)
; 2x4: (d3,d7)
; 8x2: (d0,d2),(d1,d3)
; 1x2: (d0,d2),(d1,d3)
; 4x1: (d0,d1)
; write d0
; 4x1: (d2,d3)
; 8x2: (d4,d6),(d5,d7)
; 1x2: (d4,d6),(d5,d7)
; 4x1: (d4,d5),(d6,d7)

; 16x4: (d0,d4),(d1,d5),(d2,d6)
	swap    d4
	swap    d5
	swap    d6
	eor.w   d4,d0
	eor.w   d5,d1
	eor.w   d6,d2
	eor.w   d0,d4
	eor.w   d1,d5
	eor.w   d2,d6
	eor.w   d4,d0
	eor.w   d5,d1
	eor.w   d6,d2
	swap    d4
	swap    d5
	swap    d6

; 2x4: (d0,d4),(d1,d5),(d2,d6)
	move.l  d4,d7
	lsr.l   #2,d7
	eor.l   d0,d7
	and.l   #$33333333,d7
	eor.l   d7,d0
	lsl.l   #2,d7
	eor.l   d7,d4

	move.l  d5,d7
	lsr.l   #2,d7
	eor.l   d1,d7
	and.l   #$33333333,d7
	eor.l   d7,d1
	lsl.l   #2,d7
	eor.l   d7,d5

	move.l  d6,d7
	lsr.l   #2,d7
	eor.l   d2,d7
	and.l   #$33333333,d7
	eor.l   d7,d2
	lsl.l   #2,d7
	eor.l   d7,d6

	exg     a0,d6           ; d7 -> d6
							; d6 -> a2

; 16x4: (d3,d7)

	swap    d6
	eor.w   d6,d3
	eor.w   d3,d6
	eor.w   d6,d3
	swap    d6

; 2x4 (d3,d7)

	move.l  d6,d7
	lsr.l   #2,d7
	eor.l   d3,d7
	and.l   #$33333333,d7
	eor.l   d7,d3
	lsl.l   #2,d7
	eor.l   d7,d6

; 8x2: (d0,d2),(d1,d3)

	move.l  d2,d7
	lsr.l   #8,d7
	eor.l   d0,d7
	and.l   #$00ff00ff,d7
	eor.l   d7,d0
	lsl.l   #8,d7
	eor.l   d7,d2

	move.l  d3,d7
	lsr.l   #8,d7
	eor.l   d1,d7
	and.l   #$00ff00ff,d7
	eor.l   d7,d1
	lsl.l   #8,d7
	eor.l   d7,d3

; 1x2: (d0,d2),(d1,d3)

	move.l  d2,d7
	lsr.l   #1,d7
	eor.l   d0,d7
	and.l   #$55555555,d7
	eor.l   d7,d0
	add.l   d7,d7
	eor.l   d7,d2

	move.l  d3,d7
	lsr.l   #1,d7
	eor.l   d1,d7
	and.l   #$55555555,d7
	eor.l   d7,d1
	add.l   d7,d7
	eor.l   d7,d3

; 4x1: (d0,d1)

	move.l  d1,d7
	lsr.l   #4,d7
	eor.l   d0,d7
	and.l   #$0f0f0f0f,d7
	eor.l   d7,d0
c2p8_p7_1
	move.l  d0,$12341234.l(a2)
	lsl.l   #4,d7
	eor.l   d7,d1

; 4x1: (d2,d3)

	move.l  d3,d7
	lsr.l   #4,d7
	eor.l   d2,d7
	and.l   #$0f0f0f0f,d7
	eor.l   d7,d2
	lsl.l   #4,d7
	eor.l   d7,d3

	move.l  a0,d0               ; d6 -> d0

; 8x2: (d4,d6),(d5,d7)

	move.l  d0,d7
	lsr.l   #8,d7
	eor.l   d4,d7
	and.l   #$00ff00ff,d7
c2p8_p3_1
	move.l  d1,$12341234.l(a2)
	eor.l   d7,d4
	lsl.l   #8,d7
	eor.l   d7,d0

	move.l  d6,d7
	lsr.l   #8,d7
	eor.l   d5,d7
	and.l   #$00ff00ff,d7
	eor.l   d7,d5
	lsl.l   #8,d7
	eor.l   d7,d6

; 1x2: (d4,d6),(d5,d7)

	move.l  d0,d7
	lsr.l   #1,d7
	eor.l   d4,d7
	and.l   #$55555555,d7
c2p8_p6_1
	move.l  d2,$12341234.l(a2)
	eor.l   d7,d4
	add.l   d7,d7
	eor.l   d7,d0

	move.l  d6,d7
	lsr.l   #1,d7
	eor.l   d5,d7
	and.l   #$55555555,d7
	eor.l   d7,d5

	add.l   d7,d7
	eor.l   d7,d6

; 4x1: (d4,d5),(d6,d7)

	move.l  d5,d7
	lsr.l   #4,d7
	eor.l   d4,d7
	and.l   #$0f0f0f0f,d7
c2p8_p2_1
	move.l  d3,$12341234.l(a2)
	eor.l   d7,d4
	lsl.l   #4,d7
	eor.l   d7,d5

	move.l  d6,d7
	lsr.l   #4,d7
	eor.l   d0,d7
	and.l   #$0f0f0f0f,d7
	eor.l   d7,d0
	lsl.l   #4,d7
	eor.l   d7,d6

	move.l  d4,d7
	move.l  d5,a4
	move.l  d0,a5
	move.l  d6,a1

	cmp.l   a3,a6
	beq     c2p8_end
c2p8_x1
	move.l  (a6)+,d0
	move.l  (a6)+,d1
	move.l  (a6)+,d2
	move.l  (a6)+,d3
	move.l  (a6)+,d4
	move.l  (a6)+,d5
	move.l  (a6)+,d6
	move.l  (a6)+,a0

c2p8_p5_1
	move.l  d7,$12341234.l(a2)

; 16x4: (d0,d4),(d1,d5),(d2,d6)
	swap    d4
	swap    d5
	swap    d6
	eor.w   d4,d0
	eor.w   d5,d1
	eor.w   d6,d2
	eor.w   d0,d4
	eor.w   d1,d5
	eor.w   d2,d6
	eor.w   d4,d0
	eor.w   d5,d1
	eor.w   d6,d2
	swap    d4
	swap    d5
	swap    d6
; 2x4: (d0,d4),(d1,d5),(d2,d6)
	move.l  d4,d7
	lsr.l   #2,d7
	eor.l   d0,d7
c2p8_p1_1
	move.l  a4,$12341234.l(a2)
	and.l   #$33333333,d7
	eor.l   d7,d0
	lsl.l   #2,d7
	eor.l   d7,d4

	move.l  d5,d7
	lsr.l   #2,d7
	eor.l   d1,d7
	and.l   #$33333333,d7
	eor.l   d7,d1
	lsl.l   #2,d7
	eor.l   d7,d5

	move.l  d6,d7
	lsr.l   #2,d7
	eor.l   d2,d7
	and.l   #$33333333,d7
	eor.l   d7,d2
	lsl.l   #2,d7
	eor.l   d7,d6
	exg     a0,d6           ; d7 -> d6
							; d6 -> a2
; 16x4: (d3,d7)

	swap    d6
c2p8_p4_1
	move.l  a5,$12341234.l(a2)
	eor.w   d6,d3
	eor.w   d3,d6
	eor.w   d6,d3
	swap    d6

; 2x4 (d3,d7)

	move.l  d6,d7
	lsr.l   #2,d7
	eor.l   d3,d7
	and.l   #$33333333,d7
	eor.l   d7,d3
	lsl.l   #2,d7
	eor.l   d7,d6

; 8x2: (d0,d2),(d1,d3)

	move.l  d2,d7
	lsr.l   #8,d7
	eor.l   d0,d7
	and.l   #$00ff00ff,d7
	eor.l   d7,d0
	lsl.l   #8,d7
	eor.l   d7,d2

	move.l  d3,d7
	lsr.l   #8,d7
	eor.l   d1,d7
	and.l   #$00ff00ff,d7
	move.l  a1,(a2)+
	eor.l   d7,d1
	lsl.l   #8,d7
	eor.l   d7,d3

; 1x2: (d0,d2),(d1,d3)

	move.l  d2,d7
	lsr.l   #1,d7
	eor.l   d0,d7
	and.l   #$55555555,d7
	eor.l   d7,d0
	add.l   d7,d7
	eor.l   d7,d2

	move.l  d3,d7
	lsr.l   #1,d7
	eor.l   d1,d7
	and.l   #$55555555,d7
	eor.l   d7,d1
	add.l   d7,d7
	eor.l   d7,d3

; 4x1: (d0,d1)

	move.l  d1,d7
	lsr.l   #4,d7
	eor.l   d0,d7
	and.l   #$0f0f0f0f,d7
	eor.l   d7,d0
c2p8_p7_2
	move.l  d0,$12341234.l(a2)
	lsl.l   #4,d7
	eor.l   d7,d1

; 4x1: (d2,d3)

	move.l  d3,d7
	lsr.l   #4,d7
	eor.l   d2,d7
	and.l   #$0f0f0f0f,d7
	eor.l   d7,d2
	lsl.l   #4,d7
	eor.l   d7,d3

	move.l  a0,d0               ; d6 -> d0

; 8x2: (d4,d6),(d5,d7)

	move.l  d0,d7
	lsr.l   #8,d7
	eor.l   d4,d7
	and.l   #$00ff00ff,d7
c2p8_p3_2
	move.l  d1,$12341234.l(a2)
	eor.l   d7,d4
	lsl.l   #8,d7
	eor.l   d7,d0

	move.l  d6,d7
	lsr.l   #8,d7
	eor.l   d5,d7
	and.l   #$00ff00ff,d7
	eor.l   d7,d5
	lsl.l   #8,d7
	eor.l   d7,d6

; 1x2: (d4,d6),(d5,d7)

	move.l  d0,d7
	lsr.l   #1,d7
	eor.l   d4,d7
	and.l   #$55555555,d7
c2p8_p6_2
	move.l  d2,$12341234.l(a2)
	eor.l   d7,d4
	add.l   d7,d7
	eor.l   d7,d0

	move.l  d6,d7
	lsr.l   #1,d7
	eor.l   d5,d7
	and.l   #$55555555,d7
	eor.l   d7,d5
	add.l   d7,d7
	eor.l   d7,d6

; 4x1: (d4,d5),(d6,d7)

	move.l  d5,d7
	lsr.l   #4,d7
	eor.l   d4,d7
	and.l   #$0f0f0f0f,d7
c2p8_p2_2
	move.l  d3,$12341234.l(a2)
	eor.l   d7,d4
	lsl.l   #4,d7
	eor.l   d7,d5

	move.l  d6,d7
	lsr.l   #4,d7
	eor.l   d0,d7
	and.l   #$0f0f0f0f,d7
	eor.l   d7,d0
	lsl.l   #4,d7
	eor.l   d7,d6

	move.l  d4,d7
	move.l  d5,a4
	move.l  d0,a5
	move.l  d6,a1

	cmp.l   a3,a6
	bne     c2p8_x1
c2p8_end
c2p8_p5_2
	move.l  d7,$12341234.l(a2)
c2p8_p1_2
	move.l  a4,$12341234.l(a2)
c2p8_p4_2
	move.l  a5,$12341234.l(a2)
	move.l  a1,(a2)

	rts
_c2p8_end:

	end
