
.include "fb32x32.inc"

.include "globals.inc"

.define DEBUGOUTPUT 0
.define DIVLOOPS 4

.segment "CODE"

SINE            := $e400
CACHE           := $e500   ; must start at page
CACHE_H         := CACHE
CACHE_V         := CACHE+$20

; I never though that I require 64 bytes just for variables for a
; plasma effect. Totally worth it!

h0fstart        = localram+$00
h1fstart        = localram+$02
h0curr          = localram+$04
h1curr          = localram+$06
v0fstart        = localram+$08
v1fstart        = localram+$0a
v0curr          = localram+$0c
v1curr          = localram+$0e

tabadd          = localram+$10
h0fadd          = tabadd+$0
h1fadd          = tabadd+$2
h0add           = tabadd+$4
h1add           = tabadd+$6
v0fadd          = tabadd+$8
v1fadd          = tabadd+$a
v0add           = tabadd+$c
v1add           = tabadd+$e

tabnext         = localram+$20
h0fnext         = tabnext+$0
h1fnext         = tabnext+$2
h0next          = tabnext+$4
h1next          = tabnext+$6
v0fnext         = tabnext+$8
v1fnext         = tabnext+$a
v0next          = tabnext+$c
v1next          = tabnext+$e

tabstep         = localram+$30
h0fstep         = tabstep+$0
h1fstep         = tabstep+$2
h0step          = tabstep+$4
h1step          = tabstep+$6
v0fstep         = tabstep+$8
v1fstep         = tabstep+$a
v0step          = tabstep+$c
v1step          = tabstep+$e

paramend        = localram+$40

plasma_idx      = paramend+$00
steps_left      = paramend+$01

.segment "DATA"

myschedule:
   .word $0000, plasma_init   ;0
   .word $0001, plasma_calc
   .word $0020, plasma_next   ;1
   .word $0021, plasma_calc
   .word $0080, plasma_next   ;2
   .word $0081, plasma_calc
   .word $00c0, plasma_next   ;3
   .word $00c1, plasma_calc
.if SHORTEST
   .word $00ff, schedulenext
.else
   .word $0100, plasma_next   ;4
   .word $0101, plasma_calc
   .word $0140, plasma_next   ;5
   .word $0141, plasma_calc
   .word $0180, plasma_next   ;6
   .word $0181, plasma_calc
   .word $01c0, plasma_next   ;7
   .word $01c1, plasma_calc
   .word $01ff, schedulenext
.endif

plasma_init_vals:
;               horizontal              vertical
;        start,start, curr, curr,start,start, curr, curr
   .word $f800,$f800,$f800,$f800,$f800,$f800,$f800,$f800
;        fadd, fadd,  add,  add, fadd, fadd,  add,  add
   .word $0000,$0000,$0800,$0800,$0000,$0000,$0800,$0800

plasma_next_vals:
   .word $FFC0,$0080,$0800,$0800,$FF80,$0040,$0800,$0800
   .word $0032,$00d2,$0800,$0800,$0025,$00e5,$0800,$0800
   .word $FE9D,$0134,$0369,$049B,$04CD,$0486,$049C,$FDF1
   .word $FE3E,$FBDD,$0880,$FCD5,$0406,$FE79,$0B95,$FE18
   .word $0188,$FA5D,$F0CE,$FCF7,$F741,$0AFD,$F82F,$0D4C
   .word $FA32,$06B2,$FB32,$FA5B,$F906,$0C2F,$002D,$02EA
   .word $FBA5,$084A,$05BA,$0D08,$F7E8,$F882,$F01E,$F186
;   .word $0157,$fe75,$0567,$0c76,$fb69,$0356,$0687,$0975
;   .word $0200,$fd00,$0800,$0800,$fa00,$0400,$0800,$0800
;   .word $0600,$FA00,$FB00,$0200,$0700,$FD00,$0500,$FC00

.segment "CODE"

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


plasma_next:
   lda   plasma_idx
   inc   plasma_idx
   asl
   asl
   asl
   tay
   ldx   #$00
:
   lda   plasma_next_vals,y
   sta   h0fnext,x
   iny
   inx
   cpx   #$10
   bcc   :-

   ldx   #$00

@calcsteps:
   sec
   lda   tabnext+0,x       ; 16 bit addition
   sbc   tabadd+0,x
   sta   tabstep+0,x
   lda   tabnext+1,x
   sbc   tabadd+1,x
   ldy   #$04
:
   cmp   #$80
   ror                     ; divide by 32
   ror   tabstep+0,x
   dey
   bne   :-
   sta   tabstep+1,x
   inx
   inx
   cpx   #$10
   bcc   @calcsteps

.if DEBUGOUTPUT
   ldy   #$00
:
   lda   tabstep+1,y
   tax
   lda   tabstep+0,y
   int   PRHEX16
   lda   #$20
   jsr   CHROUT
   iny
   iny
   cpy   #$10
   bcc   :-
   lda   #'S'
   jsr   CHROUT
   lda   #$0a
   jsr   CHROUT
.endif

   lda   #$10 ;lda   #$20
   sta   steps_left

   jmp   plasma_calc

plasma_init:
   lda   #$07
   sta   FB32X32_COLMAP
   stz   plasma_idx
   stz   steps_left

   lda   #$90
   ldx   #>SINE
   int   GENSINE

   ldx   #$0f
:
   lda   plasma_init_vals+$00,x
   sta   h0fstart,x
   lda   plasma_init_vals+$10,x
   sta   h0fadd,x
   sta   h0fnext,x
   dex
   bpl   :-
   ; fall through

plasma_calc_axis:
   stz   vector+0
   lda   #>CACHE
   sta   vector+1

   ldx   #$00
   jsr   @subcalc

   ldx   #<(v0fstart-h0fstart)
@subcalc:
   stx   @offset+1

   clc
   lda   h0fstart+0,x      ; calculate new frame start low
   adc   h0fadd  +0,x
   sta   h0fstart+0,x
   sta   h0curr  +0,x      ; also save as current start
   lda   h0fstart+1,x      ; calculate new frame start hi
   adc   h0fadd  +1,x
   sta   h0fstart+1,x
   sta   h0curr  +1,x      ; also save as current start

   clc
   lda   h1fstart+0,x
   adc   h1fadd  +0,x
   sta   h1fstart+0,x
   sta   h1curr  +0,x
   lda   h1fstart+1,x
   adc   h1fadd  +1,x
   sta   h1fstart+1,x
   sta   h1curr  +1,x

   lda   #$20
   sta   tmp8
@offset:
   ldx   #$00

   clc
   lda   h0curr+0,x
   adc   h0add +0,x
   sta   h0curr+0,x

   lda   h0curr+1,x
   adc   h0add +1,x
   sta   h0curr+1,x
   tay

   clc
   lda   h1curr+0,x
   adc   h1add +0,x
   sta   h1curr+0,x

   lda   h1curr+1,x
   adc   h1add +1,x
   sta   h1curr+1,x
   tax

   clc
   lda   SINE,y
   adc   SINE,x
   ror
   sta   (vector)
   inc   vector+0

   dec   tmp8
   bne   @offset
   rts


plasma_calc:
   jsr   plasma_calc_axis  ; cannot be inlined due to jsr inside routine

   stz   vector+0
   lda   #>FRAMEBUFFER
   sta   vector+1

   ldy   #$1f
@loopy:
   ldx   #$1f
@loopx:
   clc
   lda   CACHE_H,x
   adc   CACHE_V,y
   ror
   sta   (vector)
   inc   vector+0
   bne   :+
   inc   vector+1
:
   dex
   bpl   @loopx
   dey
   bpl   @loopy

   lda   steps_left
   bne   @adjust
   ldx   #$0f
:
   lda   h0fnext,x
   sta   h0fadd,x
   dex
   bpl   :-
   bra   @done

@adjust:
   dec   steps_left
   ldx   #$00
:
   clc
   lda   tabadd +0,x
   adc   tabstep+0,x
   sta   tabadd +0,x
   lda   tabadd +1,x
   adc   tabstep+1,x
   sta   tabadd +1,x
   inx
   inx
   cpx   #$10
   bcc   :-

.if DEBUGOUTPUT
   ldy   #$00
:
   lda   tabadd+1,y
   tax
   lda   tabadd+0,y
   int   PRHEX16
   lda   #$20
   jsr   CHROUT
   iny
   iny
   cpy   #$10
   bcc   :-
   lda   #$0a
   jsr   CHROUT
.endif

@done:
   jmp   showfb
