
*
*   c2p2.s - c2p for bit dublets
*
*   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    _c2p2
	XDEF    @c2p2
	XDEF    _c2p2_reloc
	XDEF    @c2p2_reloc
	XDEF    _c2p2_deinit
	XDEF    @c2p2_deinit

	cnop    0,16

; relocation

_c2p2_reloc
@c2p2_reloc
	movem.l a2/a6,-(sp)
	move.l  a0,a2
	move.l  (ct_SysBase,a0),a6
	move.l  #_c2p2_end-_c2p2,d0
	move.l  #MEMF_FAST,d1
	jsr     (_LVOAllocVec,a6)
	tst.l   d0
	beq     .fail
	move.l  d0,a0
	lea     _c2p2,a1
	move.w  #_c2p2_end-_c2p2-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,(c2p2_chunkyend1-_c2p2,a0)
	move.l  d1,(c2p2_chunkyend2-_c2p2,a0)
	move.l  d1,(c2p2_chunkyend3-_c2p2,a0)
	move.l  d1,(c2p2_chunkyend4-_c2p2,a0)
	move.l  d1,(c2p2_chunkyend5-_c2p2,a0)
	move.l  (ct_BitMap+bm_Planes+4,a2),d1
	sub.l   (ct_BitMap+bm_Planes,a2),d1
	move.l  d1,(c2p2_bpl1_1-_c2p2,a0)
	move.l  d1,(c2p2_bpl1_2-_c2p2,a0)

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

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

	cnop    0,16

; deinitialization

_c2p2_deinit
@c2p2_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

	cnop    0,16

; Template for the chunky to planar routine

_c2p2
@c2p2
	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  (bm_Planes+ct_BitMap,a0),a2

	move.l  #$00FF00FF,d2
	move.l  #$0F0F0F0F,d3
	move.l  #$33333333,d4

	move.l  a1,a5                       ; chunky -> a5
c2p2_loop
	add.l   #4096,a5
	cmp.l   #$DEADBEEF,a5
c2p2_chunkyend1 EQU *-4
	bls     c2p2_skip_move
	move.l  #$DEADBEEF,a5
c2p2_chunkyend2 EQU *-4

c2p2_skip_move
	move.l  (a4)+,a0                    ; fetch the page descriptor
	move.l  (a0),d0
	btst    #PDB_M,d0
	bne     c2p2_skip

	adda.l  #4096,a1                    ; update chunky buffers
	adda.l  #2048,a2                    ; update BitPlane pointers
	adda.l  #4096,a3

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

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

	cnop    0,16

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

	move.l  a1,a0                       ; save chunky
	move.l  a3,d5                       ; save delta

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

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

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

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

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

	cnop    0,16

c2p2_found_first
	move.l  a0,a6
c2p2_found
	move.l  d5,a3
	move.l  a0,a1

	move.l  (a1)+,(a3)+                 ; update delta buffer
	move.l  (a1)+,(a3)+

	move.l  a3,d5
	move.l  a1,a0

	cmp.l   a5,a1                       ; this page
	bcc.s   c2p2_c2p

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

; a0 - chunky start
; a1 - bitplane1
; a2 - bitplane2
; a3 - chunky end

c2p2_c2p
	move.l  a0,a1
c2p2_start
	move.l  (a6)+,d0
	move.l  (a6)+,d1

	swap    d1                  ; 1st pass
	move.w  d0,d7
	move.w  d1,d0
	move.w  d7,d1
	swap    d1

	move.l  d1,d7               ; 2nd pass
	lsr.l   #8,d7
	eor.l   d0,d7
	and.l   d2,d7
	eor.l   d7,d0
	lsl.l   #8,d7
	eor.l   d7,d1

	move.l  d1,d7               ; 3rd pass
	lsr.l   #4,d7
	eor.l   d0,d7
	and.l   d3,d7
	eor.l   d7,d0
	lsl.l   #4,d7
	eor.l   d7,d1

	move.l  d1,d7               ; 4th pass
	lsr.l   #2,d7
	eor.l   d0,d7
	and.l   d4,d7
	eor.l   d7,d0
	lsl.l   #2,d7
	eor.l   d7,d1

	move.l  d1,d7               ; 5th pass
	lsr.l   #1,d7
	eor.l   d0,d7
	and.l   #$55555555,d7
	eor.l   d7,d0
	lsl.l   #1,d7
	eor.l   d7,d1

	move.l  d0,d6
	move.l  d1,d5

	cmp.l   a6,a1
	beq     c2p2_end
c2p2_x1
	move.l  (a6)+,d0
	move.l  (a6)+,d1

	move.l  d6,($12341234,a2)
c2p2_bpl1_1 EQU *-4

	swap    d1                  ; 1st pass  1
	move.w  d0,d7               ;           1
	move.w  d1,d0               ;           sOEP
	move.w  d7,d1               ;           1
	swap    d1                  ;           1

	move.l  d1,d7               ; 2nd pass  1
	lsr.l   #8,d7               ;           1
	eor.l   d0,d7               ;           1
	and.l   d2,d7               ;           1
	eor.l   d7,d0               ;           1
	lsl.l   #8,d7               ;           1
	eor.l   d7,d1               ;           1

	move.l  d1,d7               ; 3rd pass  1
	lsr.l   #4,d7               ;           1
	eor.l   d0,d7               ;           1
	and.l   d3,d7               ;           1
	eor.l   d7,d0               ;           1
	lsl.l   #4,d7               ;           1
	eor.l   d7,d1               ;           1 = 18 cycles between chip writes
								; should be free from 040/25 upwards
	move.l  d5,(a2)+

	move.l  d1,d7               ; 4th pass
	lsr.l   #2,d7
	eor.l   d0,d7
	and.l   d4,d7
	eor.l   d7,d0
	lsl.l   #2,d7
	eor.l   d7,d1

	move.l  d1,d7               ; 5th pass
	lsr.l   #1,d7
	eor.l   d0,d7
	and.l   #$55555555,d7
	eor.l   d7,d0
	lsl.l   #1,d7
	eor.l   d7,d1

	move.l  d0,d6
	move.l  d1,d5

	cmp.l   a6,a1
	bne     c2p2_x1
c2p2_end
	move.l  d6,($12341234,a2)
c2p2_bpl1_2 EQU *-4
	move.l  a6,a1
	addq.l  #8,a1
	move.l  d5,(a2)+
	addq.l  #4,a2
	cmp.l   a5,a1
	bcs     c2p2_iloop
	beq     c2p2_skipper

	subq.l  #4,a2
	subq.l  #8,a1
c2p2_skipper
	cmp.l   #$DEADBEEF,a1
c2p2_chunkyend5 EQU *-4
	bcs     c2p2_loop

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