
.include "fb32x32.inc"

TWISTER_GFX    = $e000        ; must be 4k aligned
TWISTER_GFX2   = TWISTER_GFX + $400

.include "globals.inc"

vector0     = localram+$00    ; only used for init, can be shared
index       = localram+$00    ; 32 bytes

.segment "PADATA"

twister_gfx:
.incbin "gfx/twister.bin"

.assert <* = 0, error, "not page aligned"

.segment "DATA"

addvalues:
   .byte $00,$01,$02,$03,$04,$05,$06,$07,$08,$09,$0a,$0b,$0c,$0d,$0e,$0f
   .byte $0f,$0e,$0d,$0c,$0b,$0a,$09,$08,$07,$06,$05,$04,$03,$02,$01,$00
   .byte $00,$ff,$fe,$fd,$fc,$fb,$fa,$f9,$f8,$f7,$f6,$f5,$f4,$f3,$f2,$f1
   .byte $f1,$f2,$f3,$f4,$f5,$f6,$f7,$f8,$f9,$fa,$fb,$fc,$fd,$fe,$ff,$00

myschedule:
   .word $0000, twister_init
   .word $0001, twister_rotate
   .word $0040, twister_scroll
.if SHORTEST
   .word $0080, twister_twist_1
   ;.word $0081, twister_twist_trap
   .word $00c0, twister_twist_2
   .word $00ff, schedulenext
.else
   .word $00c0, twister_twist_1
   ;.word $00c1, twister_twist_trap
   .word $0100, twister_twist_2
   .word $017f, schedulenext
.endif

.segment "CODE"

twister:
   lda   #<myschedule
   ldx   #>myschedule
   jmp   subschedule


twister_init:
   lda   #FB32X32_CMAP_VDC
   sta   FB32X32_COLMAP

   lda   #>twister_gfx
   stz   vector0+0
   sta   vector0+1
   lda   #>TWISTER_GFX
   stz   vector1+0
   sta   vector1+1
   lda   #>TWISTER_GFX2
   stz   vector2+0
   sta   vector2+1

   ldx   #>(TWISTER_GFX2-TWISTER_GFX)
   ldy   #$00
@loop:
   lda   (vector0),y       ; 5= 5
   sta   (vector1),y       ; 5=10
   beq   :+                ; 2=12
   eor   #$70              ; 2=14
:
   sta   (vector2),y       ; 5=19
   iny                     ; 2=21
   bne   @loop             ; 3=24 * 1024 = 24576 almost a full frame
   inc   vector0+1
   inc   vector1+1
   inc   vector2+1
   dex
   bne   @loop
   rts

twister_twist_2:
   lda   frmcnt+0
   eor   #$ff
   inc
   asl
   asl
   clc
.if SHORTEST
   adc   #$80
.else
   adc   #$c0
.endif
   bra   twister_twist_0

twister_twist_1:
.if SHORTEST
   lda   #$80
.else
   lda   #$c0
.endif
twister_twist_0:
   pha

   lda   frmcnt+0
   clc
   adc   #$05
   and   #$3f
   tay

   ldx   #$00
   pla
   lda   frmcnt+0
:
   clc
   adc   addvalues,y
   sta   index,x
   inx
   cpx   #$20
   bcc   :-

   ldx   #$1f
:
   clc
   lda   index,x
   lsr
   lsr
   sta   index,x
   dex
   bpl   :-
   bra   twister_show


twister_scroll:
   ldx   #$00
@loop:
   lda   index+1,x
   sta   index+0,x
   inx
   cpx   #$1f
   bcc   @loop
   inc
   and   #$3f
   sta   index+$1f
   bra   twister_show


twister_rotate:
   ldx   #$00
   lda   frmcnt+0
   clc
   adc   #$10
   and   #$3f
@loop:
   sta   index,x
   inx
   cpx   #$20
   bcc   @loop
   ; fall through to twister show


twister_show:
   lda   #$1f
   sta   FB32X32_WIDTH
   stz   FB32X32_HEIGHT
   sta   FB32X32_STEP

   ldx   #$00
@loop:
   ; input:  %0000 0111 00ooo ooo
   ; output: %1110 0ooo ooo0 0000
   lda   #$07
   sta   tmp8
   lda   index,x
   asl
   rol   tmp8
   asl
   rol   tmp8
   asl
   rol   tmp8
   asl
   rol   tmp8
   asl
   rol   tmp8
   sta   FB32X32_SRC+0
   lda   tmp8
   sta   FB32X32_SRC+1

   stz   FB32X32_DEST_X
   stx   FB32X32_DEST_Y

   cpx   #$1f
   beq   @done
   inx
   stz   FB32X32_COPYN
   bra   @loop

@done:
   stz   FB32X32_COPY
   rts
