
*
*   c2p8.s - chunky to planar for bytes
*   Copyright (C) 1997 Aki Laukkanen
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation; either version 2 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program; if not, write to the Free Software Foundation,
*   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*

	include "exec/types.i"
	include "exec/memory.i"
	include "lvo/exec_lib.i"
	include "mmu.i"
	include "evd_context.i"


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

	cnop    0,16

_c2p8_reloc
@c2p8_reloc
	movem.l a2/a6,-(sp)
	move.l  a0,a2
	move.l  (ct_SysBase,a0),a6
	move.l  #_c2p8_end-_c2p8,d0
	move.l  #MEMF_FAST,d1
	jsr     (_LVOAllocVec,a6)
	tst.l   d0
	beq     .fail
	move.l  d0,a0
	lea     _c2p8,a1
	move.w  #_c2p8_end-_c2p8-1,d1
.loop
	move.b  (a1)+,(a0)+
	dbf     d1,.loop

	move.l  d0,a0
	move.l  (ct_ChunkyBuffer,a2),d1
	add.l   (ct_Size,a2),d1
	move.l  d1,(c2p8_chunkyend1-_c2p8,a0)
	move.l  d1,(c2p8_chunkyend2-_c2p8,a0)
	move.l  d1,(c2p8_chunkyend3-_c2p8,a0)
	move.l  d1,(c2p8_chunkyend4-_c2p8,a0)
	move.l  d1,(c2p8_chunkyend5-_c2p8,a0)
	move.l  (ct_BitMap+bm_Planes+4,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p8_p1_1-_c2p8,a0)
	move.l  d1,(c2p8_p1_2-_c2p8,a0)
	move.l  (ct_BitMap+bm_Planes+8,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p8_p2_1-_c2p8,a0)
	move.l  d1,(c2p8_p2_2-_c2p8,a0)
	move.l  (ct_BitMap+bm_Planes+12,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p8_p3_1-_c2p8,a0)
	move.l  d1,(c2p8_p3_2-_c2p8,a0)
	move.l  (ct_BitMap+bm_Planes+16,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p8_p4_1-_c2p8,a0)
	move.l  d1,(c2p8_p4_2-_c2p8,a0)
	move.l  (ct_BitMap+bm_Planes+20,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p8_p5_1-_c2p8,a0)
	move.l  d1,(c2p8_p5_2-_c2p8,a0)
	move.l  (ct_BitMap+bm_Planes+24,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p8_p6_1-_c2p8,a0)
	move.l  d1,(c2p8_p6_2-_c2p8,a0)
	move.l  (ct_BitMap+bm_Planes+28,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p8_p7_1-_c2p8,a0)
	move.l  d1,(c2p8_p7_2-_c2p8,a0)

	move.l  d0,a2
	jsr     (_LVOCacheClearU,a6)
	move.l  a2,d0

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

	cnop    0,16


_c2p8_deinit
@c2p8_deinit
	movem.l a2/a6,-(sp)
	move.l  a0,a2
	move.l  (ct_SysBase,a2),a6
	move.l  (ct_C2P,a2),a1
	jsr     (_LVOFreeVec,a6)
	clr.l   (ct_C2P,a2)
	movem.l (sp)+,a2/a6
	rts

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

	move.l  (ct_ChunkyBuffer,a0),a1
	move.l  (ct_DeltaBuffer,a0),a3
	move.l  (ct_PageDesc,a0),a4
	move.l  (ct_BitMap+bm_Planes,a0),a2

	move.l  a1,a5                       ; a5 : end of the MMU page
c2p8_loop
	add.l   #$1000,a5

	cmp.l   #$DEADBEEF,a5               ; test with the end of the chunky buffer
c2p8_chunkyend1 EQU *-4                 ; self modify
	bls     c2p8_skip_move
	move.l  #$DEADBEEF,a5
c2p8_chunkyend2 EQU *-4
c2p8_skip_move
	move.l  (a4)+,a0                    ; fetch the page descriptor
	move.l  (a0),d0
	btst    #PDB_M,d0
	bne     c2p8_skip

	adda.l  #$1000,a1                   ; update chunky buffers
	add.l   #$200,a2                    ; update BitPlane pointers
	adda.l  #$1000,a3

	cmp.l   #$DEADBEEF,a1               ; check if more to c2p
c2p8_chunkyend3 EQU *-4
	bcs     c2p8_loop

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

	cnop    0,16

c2p8_skip
	bclr    #PDB_M,d0                   ; modified bit was set
	move.l  d0,(a0)
c2p8_iloop

	move.l  a1,a0                       ; chunkybuffer -> a0
	move.l  a3,d5                       ; deltabuffer -> a0

	cmp.l   (a1)+,(a3)+                 ; compare chunky and delta buffers
	bne.w   c2p8_found_first
	cmp.l   (a1)+,(a3)+
	bne     c2p8_found_first
	cmp.l   (a1)+,(a3)+
	bne     c2p8_found_first
	cmp.l   (a1)+,(a3)+
	bne     c2p8_found_first
	cmp.l   (a1)+,(a3)+                 ; compare chunky and delta buffers
	bne.w   c2p8_found_first
	cmp.l   (a1)+,(a3)+
	bne     c2p8_found_first
	cmp.l   (a1)+,(a3)+
	bne     c2p8_found_first
	cmp.l   (a1)+,(a3)+
	bne     c2p8_found_first

	addq.l  #4,a2                       ; update bitplane and chunky pointers

	cmp.l   a5,a1                       ; check if end of the current page
	bcs     c2p8_iloop

	cmp.l   #$DEADBEEF,a1               ; check if end of the chunky buffer
c2p8_chunkyend4 EQU *-4
	bcs     c2p8_loop

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

	cnop    0,16

c2p8_found_first
	move.l  a0,a6                       ; address from where we should start c2ping
c2p8_found
	move.l  d5,a3                       ; backup these
	move.l  a0,a1

	move16  (a1)+,(a3)+                 ; use move16 to copy the data to
										; deltabuffer - fastest way
										; by far because it uses burst writes and no copyback
	move16  (a1)+,(a3)+


	move.l  a3,d5                       ; update backups
	move.l  a1,a0

	cmp.l   a5,a1                       ; this page
	bcc.s   c2p8_c2p                    ; end of so lets start c2ping

	cmp.l   (a3)+,(a1)+                 ; compare chunky and delta buffers
	bne.s   c2p8_found                      ; if difference was found back to loop
	cmp.l   (a3)+,(a1)+
	bne.s   c2p8_found
	cmp.l   (a3)+,(a1)+
	bne.s   c2p8_found
	cmp.l   (a3)+,(a1)+
	bne.s   c2p8_found
	cmp.l   (a3)+,(a1)+                 ; compare chunky and delta buffers
	bne.s   c2p8_found                      ; if difference was found back to loop
	cmp.l   (a3)+,(a1)+
	bne.s   c2p8_found
	cmp.l   (a3)+,(a1)+
	bne.s   c2p8_found
	cmp.l   (a3)+,(a1)+
	bne.s   c2p8_found

c2p8_c2p
	move.l  a3,-(sp)
	move.l  a4,-(sp)
	move.l  a5,-(sp)
	move.l  a0,a3
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
	move.l  d0,($12341234,a2)
c2p8_p7_1 EQU *-4
	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
	move.l  d1,($12341234,a2)
c2p8_p3_1 EQU *-4
	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
	move.l  d2,($12341234,a2)
c2p8_p6_1 EQU *-4
	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
	move.l  d3,($12341234,a2)
c2p8_p2_1 EQU *-4
	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

	move.l  d7,($12341234,a2)
c2p8_p5_1 EQU *-4

; 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
	move.l  a4,($12341234,a2)
c2p8_p1_1 EQU *-4
	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
	move.l  a5,($12341234,a2)
c2p8_p4_1 EQU *-4
	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
	move.l  d0,($12341234,a2)
c2p8_p7_2 EQU *-4
	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
	move.l  d1,($12341234,a2)
c2p8_p3_2 EQU *-4
	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
	move.l  d2,($12341234,a2)
c2p8_p6_2 EQU *-4
	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
	move.l  d3,($12341234,a2)
c2p8_p2_2 EQU *-4
	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
	move.l  d7,($12341234,a2)
c2p8_p5_2 EQU *-4
	move.l  a4,($12341234,a2)
c2p8_p1_2 EQU *-4
	move.l  a5,($12341234,a2)
c2p8_p4_2 EQU *-4
	move.l  a1,(a2)+
	addq.l  #4,a2
	lea     (32,a6),a1
	move.l  (sp)+,a5
	move.l  (sp)+,a4
	move.l  (sp)+,a3

	cmp.l   a5,a1
	bcs     c2p8_iloop
	beq     c2p8_skipper

	subq.l  #4,a2
	lea     (-32,a1),a1
c2p8_skipper
	cmp.l   #$DEADBEEF,a1
c2p8_chunkyend5 EQU *-4
	bcs     c2p8_loop

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