WBStartup
NoCli

; 040/25 results:

; 320x200 @46fps DoublePAL or 49.2fps PAL
; 320x256 @34.2fps DoublePAL or 37.9fps PAL
; 320x240 @37fps DoublePAL or 40.6fps PAL

; 060/50 results:

; 320x256 @50fps PAL
; 320x200 @66fps PAL

#c2pBPLX=320
#c2pBPLY=256
#c2pBPLSIZE=(#c2pBPLX*#c2pBPLY)/8

#scrwidth=#c2pBPLX
#scrheight=#c2pBPLY
#screensize=#scrwidth*#scrheight

; Date: 20-Jan-1998     Mikael Kalms (Scout/C-Lous & more)
;         Email: mikael@kalms.org
;
; About:
;   1x1 8bpl cpu5 C2P for contigous bitplanes and no horizontal modulo
;
;   This routine is intended for use on all 68040 and 68060 based systems.
;   It is not designed to perform well on 68020-030.
;
;   This routine is released into the public domain. It may be freely used
;   for non-commercial as well as commercial purposes. A short notice via
;   email is always appreciated, though.
;
; Timings:
;   ~130% on (a1200 Blizzard) 040-25
;   Estimated to run at copyspeed on 040-40 and 060
;
; Features:
;   Performs CPU-only C2P conversion using rather state-of-the-art (as of
;   the creation date, anyway) techniques
;   Handles bitplanes creens of virtually any size (4GB)
;
; Restrictions:
;   Chunky-buffer must be an even multiple of 32 pixels wide
;   If incorrect/invalid parameters are specified, the routine will
;   most probably crash.
;
; c2p1x1_8_c5_040_smcinit   changes the bitplane-size &
;         chunkybuffer size/pos
; c2p1x1_8_c5_040_init      sets only the chunkybuffer size/pos
; c2p1x1_8_c5_040     performs the actual c2p conversion
;

Statement c2p040prefs{A.l,B.l,C.l,D.l}

  ;This routine DOES NOT WORK!

  ;A.l=d0=width.w
  ;B.l=d1=height.w
  ;C.w=d2=planarwidth.w
  ;D.w=d3=planarheight.w

  MULU  d2,d3
  MOVE.l  d3,d5

; d0.w  chunkyx [chunky-pixels]
; d1.w  chunkyy [chunky-pixels]
; d3.w  scroffsy [screen-pixels]
; d5.l  bplsize [bytes] -- offset between one row in one bpl and the next bpl

  MOVEQ.l #0,d3 ; Y offset

_c2p1x1_8_c5_040_smcinit
c2p1x1_8_c5_040_smcinit
  MOVEM.l d3/a6,-(a7)
  MULU.w  d0,d3
  LSR.l #3,d3
  MOVE.l  d3,c2p1x1_8_c5_040_scroffs
  MULU.w  d0,d1
  MOVE.l  d1,c2p1x1_8_c5_040_pixels
  MOVE.l  d5,d0
  LSL.l #3,d0
  SUB.l d5,d0
  MOVE.l  d0,c2p1x1_8_c5_040_smc1-4
  ADDQ.l  #4,d0
  MOVE.l  d0,c2p1x1_8_c5_040_smc5-4
  MOVE.l  d5,d0
  LSL.l #2,d0
  MOVE.l  d0,c2p1x1_8_c5_040_smc2-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc4-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc6-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc8-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc10-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc12-4
  SUB.l d5,d0
  MOVE.l  d0,c2p1x1_8_c5_040_smc3-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc7-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc9-4
  MOVE.l  d0,c2p1x1_8_c5_040_smc11-4
  MOVE.l  execbase,a6
  JSR _LVOCacheClearU(a6)
  MOVEM.l (a7)+,d3/a6
AsmExit
End Statement

Statement c2p040init{A.l,B.l}

  ;A.l=d0=Width.w
  ;B.l=d1=Height.w

; d0.w  chunkyx [chunky-pixels]
; d1.w  chunkyy [chunky-pixels]
; d3.w  scroffsy [screen-pixels]

  MOVEQ.l #0,d3 ; Y offset

_c2p1x1_8_c5_040_init
c2p1x1_8_c5_040_init
  MULU.w  d0,d3
  LSR.l #3,d3
  MOVE.l  d3,c2p1x1_8_c5_040_scroffs
  MULU.w  d0,d1
  MOVE.l  d1,c2p1x1_8_c5_040_pixels
AsmExit
End Statement

Statement c2p040{A.l,B.l}

  MOVE.l  d0,a0 ; Chunky
  MOVE.l  d1,a1 ; Planar

; a0  c2pscreen
; a1  bitplanes
#_LVOCacheClearU=-$27C
#execbase=$4
_c2p1x1_8_c5_040
c2p1x1_8_c5_040
  MOVEM.l a3-a6,-(a7)

  ADD.l #c2pBPLSIZE*7,a1
c2p1x1_8_c5_040_smc1
  ADD.l c2p1x1_8_c5_040_scroffs,a1

  MOVE.l  c2p1x1_8_c5_040_pixels,a2
  MOVE.l  a2,d0 ; byPWest
  TST.l d0 ;
  BEQ _none
  ADD.l a0,a2

  MOVE.l  (a0)+,d0
  MOVE.l  (a0)+,d1
  MOVE.l  (a0)+,d2
  MOVE.l  (a0)+,d3
  MOVE.l  (a0)+,d4
  MOVE.l  (a0)+,d5
  MOVE.l  (a0)+,a5
  MOVE.l  (a0)+,a6

  SWAP  d4      ; Swap 16x4, part 1
  SWAP  d5
  EOR.w d0,d4
  EOR.w d1,d5
  EOR.w d4,d0
  EOR.w d5,d1
  EOR.w d0,d4
  EOR.w d1,d5
  SWAP  d4
  SWAP  d5

  MOVE.l  d4,d6     ; Swap 2x4, part 1
  MOVE.l  d5,d7
  LSR.l #2,d6
  LSR.l #2,d7
  EOR.l d0,d6
  EOR.l d1,d7
  AND.l #$33333333,d6
  AND.l #$33333333,d7
  EOR.l d6,d0
  EOR.l d7,d1
  LSL.l #2,d6
  LSL.l #2,d7
  EOR.l d6,d4
  EOR.l d7,d5

  EXG d4,a5
  EXG d5,a6

  SWAP  d4      ; Swap 16x4, part 2
  SWAP  d5
  EOR.w d2,d4
  EOR.w d3,d5
  EOR.w d4,d2
  EOR.w d5,d3
  EOR.w d2,d4
  EOR.w d3,d5
  SWAP  d4
  SWAP  d5

  MOVE.l  d4,d6     ; Swap 2x4, part 1
  MOVE.l  d5,d7
  LSR.l #2,d6
  LSR.l #2,d7
  EOR.l d2,d6
  EOR.l d3,d7
  AND.l #$33333333,d6
  AND.l #$33333333,d7
  EOR.l d6,d2
  EOR.l d7,d3
  LSL.l #2,d6
  LSL.l #2,d7
  EOR.l d6,d4
  EOR.l d7,d5

  MOVE.l  d1,d6     ; Swap 4x1, part 1
  MOVE.l  d3,d7
  LSR.l #4,d6
  LSR.l #4,d7
  EOR.l d0,d6
  EOR.l d2,d7
  AND.l #$0f0f0f0f,d6
  AND.l #$0f0f0f0f,d7
  EOR.l d6,d0
  EOR.l d7,d2
  LSL.l #4,d6
  LSL.l #4,d7
  EOR.l d6,d1
  EOR.l d7,d3

  BRA _start

  Even8
  Even8
_x
  MOVE.l  (a0)+,d0
  MOVE.l  (a0)+,d1
  MOVE.l  (a0)+,d2
  MOVE.l  (a0)+,d3
  MOVE.l  (a0)+,d4
  MOVE.l  (a0)+,d5
  MOVE.l  (a0)+,a5
  MOVE.l  (a0)+,a6

  MOVE.l  d6,(a1)
  SUB.l #c2pBPLSIZE*4,a1
c2p1x1_8_c5_040_smc2

  SWAP  d4      ; Swap 16x4, part 1
  SWAP  d5
  EOR.w d0,d4
  EOR.w d1,d5
  EOR.w d4,d0
  EOR.w d5,d1
  EOR.w d0,d4
  EOR.w d1,d5
  SWAP  d4
  SWAP  d5

  MOVE.l  d7,(a1)
  ADD.l #c2pBPLSIZE*3,a1
c2p1x1_8_c5_040_smc3

  MOVE.l  d4,d6     ; Swap 2x4, part 1
  MOVE.l  d5,d7
  LSR.l #2,d6
  LSR.l #2,d7
  EOR.l d0,d6
  EOR.l d1,d7
  AND.l #$33333333,d6
  AND.l #$33333333,d7
  EOR.l d6,d0
  EOR.l d7,d1
  LSL.l #2,d6
  LSL.l #2,d7
  EOR.l d6,d4
  EOR.l d7,d5

  EXG d4,a5
  EXG d5,a6

  SWAP  d4      ; Swap 16x4, part 2
  SWAP  d5
  EOR.w d2,d4
  EOR.w d3,d5
  EOR.w d4,d2
  EOR.w d5,d3
  EOR.w d2,d4
  EOR.w d3,d5
  SWAP  d4
  SWAP  d5

  MOVE.l  a3,(a1)
  SUB.l #c2pBPLSIZE*4,a1
c2p1x1_8_c5_040_smc4

  MOVE.l  d4,d6     ; Swap 2x4, part 1
  MOVE.l  d5,d7
  LSR.l #2,d6
  LSR.l #2,d7
  EOR.l d2,d6
  EOR.l d3,d7
  AND.l #$33333333,d6
  AND.l #$33333333,d7
  EOR.l d6,d2
  EOR.l d7,d3
  LSL.l #2,d6
  LSL.l #2,d7
  EOR.l d6,d4
  EOR.l d7,d5

  MOVE.l  d1,d6     ; Swap 4x1, part 1
  MOVE.l  d3,d7
  LSR.l #4,d6
  LSR.l #4,d7
  EOR.l d0,d6
  EOR.l d2,d7
  AND.l #$0f0f0f0f,d6
  AND.l #$0f0f0f0f,d7
  EOR.l d6,d0
  EOR.l d7,d2
  LSL.l #4,d6
  LSL.l #4,d7
  EOR.l d6,d1
  EOR.l d7,d3

  MOVE.l  a4,(a1)
  ADD.l #c2pBPLSIZE*7+4,a1
c2p1x1_8_c5_040_smc5

_start
  MOVE.l  d2,d6     ; Swap 8x2, part 1
  MOVE.l  d3,d7
  LSR.l #8,d6
  LSR.l #8,d7
  EOR.l d0,d6
  EOR.l d1,d7
  AND.l #$00ff00ff,d6
  AND.l #$00ff00ff,d7
  EOR.l d6,d0
  EOR.l d7,d1
  LSL.l #8,d6
  LSL.l #8,d7
  EOR.l d6,d2
  EOR.l d7,d3

  MOVE.l  d2,d6     ; Swap 1x2, part 1
  MOVE.l  d3,d7
  LSR.l #1,d6
  LSR.l #1,d7
  EOR.l d0,d6
  EOR.l d1,d7
  AND.l #$55555555,d6
  AND.l #$55555555,d7
  EOR.l d6,d0
  EOR.l d7,d1
  LSL.l #1,d6
  LSL.l #1,d7
  EOR.l d6,d2
  EOR.l d7,d3

  MOVE.l  d0,(a1)
  SUB.l #c2pBPLSIZE*4,a1
c2p1x1_8_c5_040_smc6

  MOVE.l  a5,d6
  MOVE.l  a6,d7
  MOVE.l  d2,a3
  MOVE.l  d3,a4

  MOVE.l  d5,d2     ; Swap 4x1, part 2
  MOVE.l  d7,d3
  LSR.l #4,d2
  LSR.l #4,d3
  EOR.l d4,d2
  EOR.l d6,d3
  AND.l #$0f0f0f0f,d2
  AND.l #$0f0f0f0f,d3
  EOR.l d2,d4
  EOR.l d3,d6

  MOVE.l  d1,(a1)
  ADD.l #c2pBPLSIZE*3,a1
c2p1x1_8_c5_040_smc7

  LSL.l #4,d2
  LSL.l #4,d3
  EOR.l d2,d5
  EOR.l d3,d7

  MOVE.l  d4,d2     ; Swap 8x2, part 2
  MOVE.l  d5,d3
  LSR.l #8,d2
  LSR.l #8,d3
  EOR.l d6,d2
  EOR.l d7,d3
  AND.l #$00ff00ff,d2
  AND.l #$00ff00ff,d3
  EOR.l d2,d6
  EOR.l d3,d7

  MOVE.l  a3,(a1)
  SUB.l #c2pBPLSIZE*4,a1
c2p1x1_8_c5_040_smc8

  LSL.l #8,d2
  LSL.l #8,d3
  EOR.l d2,d4
  EOR.l d3,d5

  MOVE.l  d4,d2     ; Swap 1x2, part 2
  MOVE.l  d5,d3
  LSR.l #1,d2
  LSR.l #1,d3
  EOR.l d6,d2
  EOR.l d7,d3
  AND.l #$55555555,d2
  AND.l #$55555555,d3

  MOVE.l  a4,(a1)
  ADD.l #c2pBPLSIZE*3,a1
c2p1x1_8_c5_040_smc9

  EOR.l d2,d6
  EOR.l d3,d7
  LSL.l #1,d2
  LSL.l #1,d3
  EOR.l d2,d4
  EOR.l d3,d5

  MOVE.l  d4,a3
  MOVE.l  d5,a4

  CMP.l a0,a2
  BNE _x

  MOVE.l  d6,(a1)
  SUB.l #c2pBPLSIZE*4,a1
c2p1x1_8_c5_040_smc10
  MOVE.l  d7,(a1)
  ADD.l #c2pBPLSIZE*3,a1
c2p1x1_8_c5_040_smc11
  MOVE.l  a3,(a1)
  SUB.l #c2pBPLSIZE*4,a1
c2p1x1_8_c5_040_smc12
  MOVE.l  a4,(a1)

_none: MOVEM.l (a7)+,a3-a6
AsmExit

Even4
c2p1x1_8_c5_040_scroffs: Dc.l 0
c2p1x1_8_c5_040_pixels: Dc.l 0
End Statement





.blitzprogram
; Setup
InitBank 0,(#scrwidth*#scrheight)+1000,2|65536 ; Chipram planar buffer
CludgeBitMap 0,#scrwidth,#scrheight,8,Bank(0)
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
c2p040init{#scrwidth,#scrheight}
VWait 20
Forbid_
VWait
ResetTimer
For time=1 To 800
  c2p040{baseaddress1,Bank(0)} ; 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

