
.include "fb32x32.inc"

.include "globals.inc"

BALLBUFFER  := $e800 ; -$c7ff , needs to be on page boundry, 2k aligned
BALLSHADOW  := $e700
BOUNCETABLE := $e600

.define     LOSSOMAN_GENERATE 1
.define     COLOR_MAP         $00
.define     COLOR_BALL_WHITE  $FF
.define     COLOR_BALL_RED    $C0
.define     COLOR_BALL_SHADOW $01
.define     COLOR_GRID_GREY   $03
.define     COLOR_GRID_PURPLE $8A

upper4      := localram+0
xpos        := upper4+1
sinidx      := xpos+1

.segment "DATA"

myschedule:
   .word $0000, grid_init
   .word $0001, shadowcalc
   .word $0002, ballcalc
   .word $000a, grid_man
   .word $0080, grid_ball
.if SHORTEST
   .word $00ff, schedulenext
.else
   .word $01ff, schedulenext
.endif

ballshape:
   .byte $50,$30,$20,$10,$10,$00,$00,$00,$00,$00,$00,$10,$10,$20,$30,$50

.segment "CODE"

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

grid_init:
.if COLOR_MAP
   lda   #COLOR_MAP
   sta   FB32X32_COLMAP    ; select right colormap
.else
   stz   FB32X32_COLMAP    ; select right colormap
.endif

.if LOSSOMAN_GENERATE
   ; this can be dropped, if run directly after "lossoman_intro"
   jsr   lossoman_generate
.endif

   ldx   #$0f
:
   lda   ballshape,x
   sta   rotable,x
   dex
   bpl   :-

   lda   #$40
   sta   sinidx
   lda   #$10
   sta   xpos

   jsr   grid_background
   jsr   bouncetable

   jmp   grid_man


bouncetable:
   lda   #$02
   ldx   #>BOUNCETABLE
   int   GENSINE

   ldx   #$00
@loop:
   lda   BOUNCETABLE,x
   cmp   #$10
   bcc   @skip
   eor   #$1f
   sta   BOUNCETABLE,x
@skip:
   inx
   bne   @loop
   rts


shadowcalc:
   lda   #COLOR_BALL_SHADOW
   ldx   #$00
:
   sta   TMPBUFFER,x       ; fill
   stz   BALLSHADOW,x      ; clear out ball shadow
   inx
   bne   :-

   lda   #>BALLSHADOW
   jsr   imgcompress
   jmp   grid_man


ballcalc:
   lda   frmcnt            ; calculate one ball per frame
   and   #$07
   tax
   jsr   checkerboard

   txa
   ora   #>BALLBUFFER      ; needs 2k alignment
   sta   @clear+2
   ldx   #$00
@clear:
   stz   BALLBUFFER,x
   inx
   bne   @clear

   jsr   imgcompress       ; A = dest page
   jmp   grid_man

checkerboard:
   ; create 16x16 pixel checkerboard
   ; input:
   ; X = offset
   ldy   #$00
@checkerloop:
   tya
   lsr
   lsr
   lsr
   lsr
   sta   upper4
   txa
   and   #$0f
   eor   upper4
   and   #$04
   bne   :+
   lda   #COLOR_BALL_WHITE
   .byte $2c
:
   lda   #COLOR_BALL_RED
   sta   TMPBUFFER,y
   inx
   iny
   bne   @checkerloop
   rts


grid_background:
   ldx   #$00
@linesloop:
   txa
   and   #$03
   cmp   #$01
   bne   :+
   lda   #COLOR_GRID_PURPLE
   .byte $2c
:
   lda   #COLOR_GRID_GREY
   sta   FRAMEBUFFER+$000,x
   sta   FRAMEBUFFER+$100,x
   sta   FRAMEBUFFER+$200,x
   sta   FRAMEBUFFER+$300,x
   inx
   bne   @linesloop

   lda   #COLOR_GRID_PURPLE
   ldx   #$1f
:
   sta   FRAMEBUFFER+$060,x
   sta   FRAMEBUFFER+$0e0,x
   sta   FRAMEBUFFER+$160,x
   sta   FRAMEBUFFER+$1e0,x
   sta   FRAMEBUFFER+$260,x
   sta   FRAMEBUFFER+$2e0,x
   sta   FRAMEBUFFER+$360,x
   sta   FRAMEBUFFER+$3e0,x
   dex
   bpl   :-

   rts

grid_man:
   jsr   grid_paint        ; paint grid
   lda   #>lossoman_mem
   bra   grid_paste

grid_ball:
   jsr   grid_paint        ; paint grid

   ; shadow first
   lda   #>BALLSHADOW
   stz   FB32X32_SRC+0
   sta   FB32X32_SRC+1

   lda   xpos
   and   #$7f
   lsr
   inc                     ; move two pixels to the right
   inc
   jsr   grid_blob
   sta   FB32X32_COPYN

   ; now the real ball
   lda   xpos
   ;lsr
   and   #$07
   ora   #>BALLBUFFER
.if 1
   pha
   stz   vector+0
   sta   vector+1
   ldy   #$00
:
   lda   (vector),y
   sta   (vector),y
   iny
   bne   :-
   pla
.endif
   ; fall through

grid_paste:
   stz   FB32X32_SRC+0
   sta   FB32X32_SRC+1

   lda   xpos
   and   #$7f
   lsr
   jsr   grid_blob
   sta   FB32X32_COPY

   ; calc next step
   inc   sinidx
   inc   sinidx
   inc   sinidx

   lda   frmcnt
   and   #$01
   bne   @done

   lda   xpos
   clc
   bpl   :+
   adc   #$fd
:
   adc   #$01

   cmp   #$21
   beq   :+
   cmp   #$80
   bne   :++
:
   eor   #$80
:
   sta   xpos

@done:
   rts

grid_paint:
   stz   FB32X32_SRC+0
   lda   #>FRAMEBUFFER
   sta   FB32X32_SRC+1

   stz   FB32X32_DEST_X
   stz   FB32X32_DEST_Y

   lda   #$1f
   sta   FB32X32_STEP
   sta   FB32X32_WIDTH
   sta   FB32X32_HEIGHT

   stz   FB32X32_COPYN
   rts

grid_blob:
   ; IN:
   ; A: xpos
   ; FB32X32_SRC set outside
   ldy   #$0f              ; default width

   sta   FB32X32_DEST_X    ; write start X position
@recheck:
   cmp   #$11              ; how check if to truncate (shadow)
   bcc   @nochange
   dey
   dec
   bra   @recheck
@nochange:

   ldx   sinidx
   lda   BOUNCETABLE,x
   sta   FB32X32_DEST_Y

   lda   #$0f
   sty   FB32X32_WIDTH     ; Y = truncated width
   sta   FB32X32_HEIGHT
   sta   FB32X32_STEP
   stz   FB32X32_TCOL
   lda   #$01
   ;sta   FB32X32_COPY
   rts
