WBStartup
NoCli

; Results on 040/25Mhz CPU:
; PAL       50Hz 320x200 256-colours runs @50fps
; DoublePAL 48Hz 320x200 256-colours runs @47.1fps
; PAL       50Hz 320x256 256-colours runs @38.3fps
; DoublePAL 48Hz 320x256 256-colours runs @35.3fps

; Results on 060/50:
; PAL @49.6fps 320x256
; PAL @66.1fps 320x200

;Width must be multiple of 32!
#scrwidth=320 ; This is the width of chunky bitmap and also of the planar bitmap
#scrheight=256 ; This is the height of the chunky bitmap and also of the planar bitmap

#screensize=#scrwidth*#scrheight ; constants needed by the c2p
#screensize4=#screensize/4
#plane=#screensize/8

Statement c2p{A.l,B.l}
.c2p

  MOVE.l  d0,a0
  MOVE.l  d1,a1

;Original sourcecode text:
;
;---------------------------------------------------------------------------
;5 pass cpu only c2p for 040/060 -
;
;~13820us for 320x256 (216 rasterlines)
;with no dma activated.
;(usual copyspeed is ~13960 us)
;
;(W) Mai 1998 by Tim Bvscke aka. Azure
;azure@gmx.net
;
;This Chunky to Planar converter is converting/writing faster than
;a usual longword loop is copying from fastmem to chipmem. (Copyspeed)
;
;This is possible due to some caching-tricks.
;
;---------------------------------------------------------------------------
;IN:
; a0   =source
; a1   =target
;----------------------------------------------------------------------------



;MERGE    d1,d2,tmp,mask,shift
Macro MERGE
  MOVE.l   `2,`3
  LSR.l   #`5,`3
    EOR.l    `1,`3
    AND.l    `4,`3
    EOR.l    `3,`1
    LSL.l   #`5,`3
    EOR.l    `3,`2
End Macro

Macro MERGE1
  MOVE.l   `2,`3
  LSR.l    #1,`3
    EOR.l    `1,`3
    AND.l    `4,`3
    EOR.l    `3,`1
    ADD.l    `3,`3
    EOR.l    `3,`2
End Macro

Macro MERGEw
    SWAP  `2
    EOR.w `1,`2
    EOR.w `2,`1
    EOR.w `1,`2
    SWAP  `2
End Macro

_chunky2planar

    MOVEM.l a3-a6,-(a7)
    MOVE.l  #screensize,d0

    LEA 0(a0,d0.l),a2
    MOVE.l  a2,smc+2

    MOVEM.l a0/a1/a6,-(a7)
    MOVE.l  $4,a6
    JSR -636(a6)  ;flush caches
    MOVEM.l (a7)+,a0/a1/a6

    MOVE.l  (a0),d0
    MOVE.l  2*4+0(a0),d2
    MOVE.l  4*4+0(a0),d4
    MOVE.l  6*4+0(a0),d6

    !MERGEw{d0,d4}
    !MERGEw{d2,d6}

    !MERGE{d0,d2,d3,#$00FF00FF,8}
    !MERGE{d4,d6,d3,#$00FF00FF,8}

    MOVE.l  1*4(a0),d1
    MOVE.l  3*4(a0),d3
    MOVE.l  5*4(a0),d5
    MOVE.l  7*4(a0),d7

    ADDA.w  #32,a0
    MOVE.l  d4,a6   ;  d3->a6

    !MERGEw{d1,d5}
    ADD.l #screensize4*1,a1
    !MERGEw{d3,d7}
    !MERGE{d5,d7,d4,#$00FF00FF,8}
    !MERGE{d1,d3,d4,#$00FF00FF,8}
    !MERGE{d0,d1,d4,#$0F0F0F0F,4}
    !MERGE{d2,d3,d4,#$0F0F0F0F,4}
    !MERGE{d6,d7,d4,#$0F0F0F0F,4}
    EXG.l d1,a6   ;d4-> a6
    !MERGE{d1,d5,d4,#$0F0F0F0F,4}
    ADD.l #screensize4*1,a1
    !MERGE{d0,d1,d4,#$33333333,2}
    !MERGE{d2,d6,d4,#$33333333,2}
    ADD.l #screensize4*1+4,a1
    !MERGE{d3,d7,d4,#$33333333,2}
    EXG.l d1,a6   ;d4=a6
    !MERGE1{d0,d2,d4,#$55555555}
    MOVE.l  d0,plane(a1) ;->Plane 7
    EXG.l d0,a6
    !MERGE{d1,d5,d4,#$33333333,2}
    !MERGE1{d0,d6,d4,#$55555555}
    MOVE.l  d0,a5
    !MERGE1{d1,d3,d4,#$55555555}
    MOVE.l  d2,(a1)
    MOVE.l  d6,a4
    MOVE.l  d1,a3
    SUB.l #screensize4*3,a1
    !MERGE1{d5,d7,d4,#$55555555}
    MOVE.l  d7,a6
    MOVE.l  d3,a2
loop
    TST.w 0*16+6(a0)
    TST.w 1*16+6(a0)
    TST.w 2*16+6(a0)
    TST.w 3*16+6(a0)

    TST.w 4*16+6(a0)
    TST.w 5*16+6(a0)
    TST.w 6*16+6(a0)
    TST.w 7*16+6(a0)  ;this is the tricky part

    MOVE.l  (a0),d0
    MOVE.l  2*4+0(a0),d2
    MOVE.l  4*4+0(a0),d4
    MOVE.l  6*4+0(a0),d6

    MOVE.l  d5,plane(a1) ;  Plane 1

    !MERGEw{d0,d4}
    !MERGEw{d2,d6}

    !MERGE{d0,d2,d3,#$00FF00FF,8}
    !MERGE{d4,d6,d3,#$00FF00FF,8}

    MOVE.l  1*4(a0),d1
    MOVE.l  3*4(a0),d3
    MOVE.l  5*4(a0),d5
    MOVE.l  7*4(a0),d7

    ADDA.l  #32,a0
    MOVE.l  a6,(a1)   ;  Plane 0
    MOVE.l  d4,a6   ;  d3->a6

    !MERGEw{d1,d5}
    ADD.l #screensize4*1,a1
    !MERGEw{d3,d7}

    MOVE.l  a3,plane(a1) ; 3

    !MERGE{d5,d7,d4,#$00FF00FF,8}
    !MERGE{d1,d3,d4,#$00FF00FF,8}
    !MERGE{d0,d1,d4,#$0F0F0F0F,4}
    !MERGE{d2,d3,d4,#$0F0F0F0F,4}
    MOVE.l  a2,(a1)   ; 2
    !MERGE{d6,d7,d4,#$0F0F0F0F,4}
    EXG.l d1,a6   ;d4-> a6
    !MERGE{d1,d5,d4,#$0F0F0F0F,4}
    ADD.l #screensize4*1,a1
    MOVE.l  a5,plane(a1) ; 5

    !MERGE{d0,d1,d4,#$33333333,2}
    !MERGE{d2,d6,d4,#$33333333,2}
    MOVE.l  a4,(a1)   ; 4
    ADD.l #screensize4*1+4,a1
    !MERGE{d3,d7,d4,#$33333333,2}
    EXG.l d1,a6   ;d4=a6

    !MERGE1{d0,d2,d4,#$55555555}

    MOVE.l  d0,plane(a1) ;->Plane 7

    EXG.l d0,a6

    !MERGE{d1,d5,d4,#$33333333,2}
    !MERGE1{d0,d6,d4,#$55555555}
    MOVE.l  d0,a5
    !MERGE1{d1,d3,d4,#$55555555}
    MOVE.l  d2,(a1)
    MOVE.l  d6,a4
    MOVE.l  d1,a3
    SUB.l #screensize4*3,a1
    !MERGE1{d5,d7,d4,#$55555555}
    MOVE.l  d7,a6
    MOVE.l  d3,a2


    MOVE.l  (a0),d0
    MOVE.l  2*4+0(a0),d2
    MOVE.l  4*4+0(a0),d4
    MOVE.l  6*4+0(a0),d6

    MOVE.l  d5,plane(a1) ;  Plane 1

    !MERGEw{d0,d4}
    !MERGEw{d2,d6}

    !MERGE{d0,d2,d3,#$00FF00FF,8}
    !MERGE{d4,d6,d3,#$00FF00FF,8}

    MOVE.l  1*4(a0),d1
    MOVE.l  3*4(a0),d3
    MOVE.l  5*4(a0),d5
    MOVE.l  7*4(a0),d7

    ADDA.l  #32,a0
    MOVE.l  a6,(a1)   ;  Plane 0
    MOVE.l  d4,a6   ;  d3->a6

    !MERGEw{d1,d5}
    ADD.l #screensize4*1,a1
    !MERGEw{d3,d7}

    MOVE.l  a3,plane(a1) ; 3

    !MERGE{d5,d7,d4,#$00FF00FF,8}
    !MERGE{d1,d3,d4,#$00FF00FF,8}
    !MERGE{d0,d1,d4,#$0F0F0F0F,4}
    !MERGE{d2,d3,d4,#$0F0F0F0F,4}
    MOVE.l  a2,(a1)   ; 2
    !MERGE{d6,d7,d4,#$0F0F0F0F,4}
    EXG.l d1,a6   ;d4-> a6
    !MERGE{d1,d5,d4,#$0F0F0F0F,4}
    ADD.l #screensize4*1,a1
    MOVE.l  a5,plane(a1) ; 5

    !MERGE{d0,d1,d4,#$33333333,2}
    !MERGE{d2,d6,d4,#$33333333,2}
    MOVE.l  a4,(a1)   ; 4
    ADD.l #screensize4*1+4,a1
    !MERGE{d3,d7,d4,#$33333333,2}
    EXG.l d1,a6   ;d4=a6

    !MERGE1{d0,d2,d4,#$55555555}

    MOVE.l  d0,plane(a1) ;->Plane 7

    EXG.l d0,a6

    !MERGE{d1,d5,d4,#$33333333,2}
    !MERGE1{d0,d6,d4,#$55555555}
    MOVE.l  d0,a5
    !MERGE1{d1,d3,d4,#$55555555}
    MOVE.l  d2,(a1)
    MOVE.l  d6,a4
    MOVE.l  d1,a3
    SUB.l #screensize4*3,a1
    !MERGE1{d5,d7,d4,#$55555555}
    MOVE.l  d7,a6
    MOVE.l  d3,a2


    MOVE.l  (a0),d0
    MOVE.l  2*4+0(a0),d2
    MOVE.l  4*4+0(a0),d4
    MOVE.l  6*4+0(a0),d6

    MOVE.l  d5,plane(a1) ;  Plane 1

    !MERGEw{d0,d4}
    !MERGEw{d2,d6}

    !MERGE{d0,d2,d3,#$00FF00FF,8}
    !MERGE{d4,d6,d3,#$00FF00FF,8}

    MOVE.l  1*4(a0),d1
    MOVE.l  3*4(a0),d3
    MOVE.l  5*4(a0),d5
    MOVE.l  7*4(a0),d7

    ADDA.l  #32,a0
    MOVE.l  a6,(a1)   ;  Plane 0
    MOVE.l  d4,a6   ;  d3->a6

    !MERGEw{d1,d5}
    ADD.l #screensize4*1,a1
    !MERGEw{d3,d7}

    MOVE.l  a3,plane(a1) ; 3

    !MERGE{d5,d7,d4,#$00FF00FF,8}
    !MERGE{d1,d3,d4,#$00FF00FF,8}
    !MERGE{d0,d1,d4,#$0F0F0F0F,4}
    !MERGE{d2,d3,d4,#$0F0F0F0F,4}
    MOVE.l  a2,(a1)   ; 2
    !MERGE{d6,d7,d4,#$0F0F0F0F,4}
    EXG.l d1,a6   ;d4-> a6
    !MERGE{d1,d5,d4,#$0F0F0F0F,4}
    ADD.l #screensize4*1,a1
    MOVE.l  a5,plane(a1) ; 5

    !MERGE{d0,d1,d4,#$33333333,2}
    !MERGE{d2,d6,d4,#$33333333,2}
    MOVE.l  a4,(a1)   ; 4
    ADD.l #screensize4*1+4,a1
    !MERGE{d3,d7,d4,#$33333333,2}
    EXG.l d1,a6   ;d4=a6

    !MERGE1{d0,d2,d4,#$55555555}

    MOVE.l  d0,plane(a1) ;->Plane 7

    EXG.l d0,a6

    !MERGE{d1,d5,d4,#$33333333,2}
    !MERGE1{d0,d6,d4,#$55555555}
    MOVE.l  d0,a5
    !MERGE1{d1,d3,d4,#$55555555}
    MOVE.l  d2,(a1)
    MOVE.l  d6,a4
    MOVE.l  d1,a3
    SUB.l #screensize4*3,a1
    !MERGE1{d5,d7,d4,#$55555555}
    MOVE.l  d7,a6
    MOVE.l  d3,a2

smc
    CMP.l #$0BADC0DE,a0
    BGE   quit

    MOVE.l  (a0),d0
    MOVE.l  2*4+0(a0),d2
    MOVE.l  4*4+0(a0),d4
    MOVE.l  6*4+0(a0),d6

    MOVE.l  d5,plane(a1) ;  Plane 1

    !MERGEw{d0,d4}
    !MERGEw{d2,d6}

    !MERGE{d0,d2,d3,#$00FF00FF,8}
    !MERGE{d4,d6,d3,#$00FF00FF,8}

    MOVE.l  1*4(a0),d1
    MOVE.l  3*4(a0),d3
    MOVE.l  5*4(a0),d5
    MOVE.l  7*4(a0),d7

    ADDA.w  #32,a0
    MOVE.l  a6,(a1)   ;  Plane 0
    MOVE.l  d4,a6   ;  d3->a6

    !MERGEw{d1,d5}
    ADD.l #screensize4*1,a1

    !MERGEw{d3,d7}

    MOVE.l  a3,plane(a1) ; 3
    !MERGE{d5,d7,d4,#$00FF00FF,8}
    !MERGE{d1,d3,d4,#$00FF00FF,8}
    !MERGE{d0,d1,d4,#$0F0F0F0F,4}
    MOVE.l  a2,(a1)   ; 2
    !MERGE{d2,d3,d4,#$0F0F0F0F,4}
    !MERGE{d6,d7,d4,#$0F0F0F0F,4}
    EXG.l d1,a6   ;d4-> a6
    !MERGE{d1,d5,d4,#$0F0F0F0F,4}
    ADD.l #screensize4*1,a1

    MOVE.l  a5,plane(a1) ; 5

    !MERGE{d0,d1,d4,#$33333333,2}
    !MERGE{d2,d6,d4,#$33333333,2}
    MOVE.l  a4,(a1)   ; 4
    ADD.l #screensize4*1+4,a1
    !MERGE{d3,d7,d4,#$33333333,2}
    EXG.l d1,a6   ;d4=a6
    !MERGE1{d0,d2,d4,#$55555555}

    MOVE.l  d0,plane(a1) ;->Plane 7

    EXG.l d0,a6
    !MERGE{d1,d5,d4,#$33333333,2}
    !MERGE1{d0,d6,d4,#$55555555}
    MOVE.l  d0,a5
    !MERGE1{d1,d3,d4,#$55555555}
    MOVE.l  d2,(a1)
    MOVE.l  d6,a4
    MOVE.l  d1,a3
    SUB.l #screensize4*3,a1
    !MERGE1{d5,d7,d4,#$55555555}
    MOVE.l  d7,a6
    MOVE.l  d3,a2

    JMP loop
quit
    MOVE.l  d5,plane(a1)
    MOVE.l  a6,(a1)
    ADD.l #screensize4*1,a1
    MOVE.l  a3,plane(a1)
    MOVE.l  a2,(a1)
    ADD.l #screensize4*1,a1
    MOVE.l  a5,plane(a1)
    MOVE.l  a4,(a1)

    MOVEM.l (a7)+,a3-a6

  AsmExit
End Statement


; The following program is just a demonstration of how to get the c2p working.
; You must cludge bitmaps to 8 bytes past the start of the planar buffer,
; but tell the c2p routine to output to 4 bytes past the start of the planar buffer.
; This is because it outputs a longword of temporary data to the planar buffer
; before commencing the conversion, and keeps the bitmap data 64-bit aligned
; so that if you are working with o/s screens they will use 64-bit datafetch.
.blitzprogram
; Setup
InitBank 0,(#scrwidth*#scrheight)+1000,2|65536 ; Chipram planar buffer
CludgeBitMap 0,#scrwidth,#scrheight,8,Bank(0)+8
InitPalette 0,256
For c=0 To 255
  AGAPalRGB 0,c,Rnd(c),Rnd(c),Rnd(c)
Next c
AGAPalRGB 0,0,0,0,0
Screen 0,0,0,#scrwidth,#scrheight,8,0,"c2p test",0,0,0
Use Palette 0
VWait 50
baseaddress1.l=AllocMem(#scrwidth*#scrheight,$10000) ; Fastram chunky buffer

; Put something into the chunky buffer so we can see it working
GetReg a0,baseaddress1
MOVE.l  #0,d0
MOVE.l  #screensize-1,d1
cloop
  MOVE.b  d0,(a0)+
  ADDQ.l  #1,d0
  SUBQ.l  #1,d1
  TST.l   d1
  BLT     done
  BRA     cloop
done

; Do the c2p test
VWait 20
Forbid_
VWait
ResetTimer
For time=1 To 800
  c2p{baseaddress1,Bank(0)+4} ; Convert chunky to planar
Next time
t=Ticks
VWait 2 : Permit_
VWait 20
FindScreen 0
Window 0,0,11,640,100,0,"Test results for c2p",0,0
WindowOutput 0
NPrint "Routine performed @ ",50/(t/800),"fps - ",t," ticks"
NPrint " "
NPrint "Press mousebutton..."
Free Screen 0
MouseWait
Free Window 0
End

