
//#resource "vcs-ca65.h"

import "vcslib.ecs"

component Bitmap
    bitmapdata: array of 0..255 baseoffset 31
    height: 0..255
end

component HasBitmap
    bitmap: [Bitmap]
end

component Colormap
    colormapdata: array of 0..255 baseoffset 31
end

component HasColormap
    colormap: [Colormap]
end

component Sprite
    plyrflags: 0..63
end

component HasXpos
    xpos: 0..255
end

component HasYpos
    ypos: 0..255
end

component SpriteSlot
    sprite: [Sprite,HasBitmap,HasColormap,HasYpos]
end

component Missile
end

system Kernel2Sprite
    locals 13
    on preframe do with [KernelSection]
---
.define KLINES {{<lines}}
.define KPAD 32
---
    on preframe do join 
    	[SpriteSlot] with
    	[Sprite,HasBitmap,HasColormap,HasYpos] limit 2
---
; set player object flags
    lda {{<plyrflags}}
    sta NUSIZ0,y
    sta REFP0,y
; calculate screen height - ypos
    lda KLINES+KPAD
    sec
    sbc {{<ypos}}
    sta {{$11}}
; calculate bitmap pointer
    stx {{$12}}		; save X (Sprite index)
    lda {{<bitmap}}     ; deref bitmap
    tax
    lda {{<Bitmap:bitmapdata}},x
    sec
    sbc {{$11}}
    sta {{$0}},y	; Y = sprite slot index
    lda {{>Bitmap:bitmapdata}},x
    sbc #0
    sta {{$2}},y
; get bitmap height
    lda {{<Bitmap:height}},x
    sta {{$8}},y
; calculate colormap pointer
    ldx {{$12}}		; restore X
    lda {{<colormap}}	; deref colormap
    tax
    lda {{<Colormap:colormapdata}},x
    sec
    sbc {{$11}}
    sta {{$4}},y
    lda {{>Colormap:colormapdata}},x
    sbc #0
    sta {{$6}},y
; save ypos
    ldx {{$12}}		; restore X
    lda {{<ypos}}
    sta {{$10}},y
---
    on preframe do once
---
; L0 L1 H0 H1 -> L0 H0 L1 H1
    lda {{$1}}
    ldy {{$2}}
    sty {{$1}}
    sta {{$2}}
    lda {{$5}}
    ldy {{$6}}
    sty {{$5}}
    sta {{$6}}
---
    on preframe do if [BGColor]
---
    lda {{<bgcolor}}
    sta COLUBK
---
    on preframe do if [Missile,HasYpos]
---
    lda KLINES
    sec
    sbc {{<ypos}}
    sta {{$12}}
---
    on kernel do with [KernelSection]
---
    ldy #0
    sty VDELP0
    iny
    sta VDELP1
---
    on kernel do with [KernelSection]
---
; define macro for each line
    .macro @DrawLine do_wsync
    .local DoDraw1
    .local DoDraw2
; draw player 0
    lda {{$8}} ; height
    dcp {{$10}} ; ypos
    bcs DoDraw1
    lda #0
    .byte $2C
DoDraw1:
    lda ({{$0}}),y
    .if do_wsync
    sta WSYNC
    .endif
    sta GRP0
    lda ({{$4}}),y
    sta COLUP0
; draw player 1
    lda {{$9}} ; height
    dcp {{$11}} ; ypos
    bcs DoDraw2
    lda #0
    .byte $2C
DoDraw2:
    lda ({{$2}}),y
    sta GRP1
    lda ({{$6}}),y
    sta COLUP1
    .endmacro
    
    ldy {{<lines}}
@LVScan:
    {{!scanline1}}
    @DrawLine 1 ; macro: draw scanline w/ WSYNC
    dey		; next scanline
    {{!scanline2}}
    @DrawLine 0 ; macro: draw scanline no WSYNC
    dey		; next scanline
    bne @LVScan	; repeat until out of lines
---
    on kernel do with [KernelSection]
---
    lda #0
    sta GRP0
    sta GRP1
    sta GRP0
    sta GRP1
---
    on scanline1 do if [Missile,HasYpos]
---
    cpy {{$12}}
    php
    pla
    sta ENAM0
---
end

system VersatilePlayfield
    locals 2
    on preframe do with [VersatilePlayfield]
---
    lda {{<data}}
    sta {{$0}}
    lda {{>data}}
    sta {{$1}}
---
    on scanline1 do with [VersatilePlayfield]
---
    lda ({{local 0}}),y
    tax
---
    on scanline2 do with [VersatilePlayfield]
---
    lda ({{local 0}}),y
    sta $00,x
---
end

system SetXPos
    on preframe do once
---
    sta HMCLR
---
    on preframe do join [SpriteSlot] with [HasXpos]
    limit 2
---
    lda {{<xpos}}
    {{!SetHorizPos}}
---
    on preframe do if [Missile,HasXpos]
---
    lda {{<xpos}}
    ldx #2
    {{!SetHorizPos}}
---
    on preframe do once
---
    sta WSYNC
    sta HMOVE
---
end

system MoveJoyX
    on joyleft do with [HasXpos]
---
    lda {{<xpos}}
    sec
    sbc #1	
    bcc @nomove
    sta {{<xpos}}
@nomove:
---
    on joyright do with [HasXpos]
---
    lda {{<xpos}}
    clc
    adc #1
    cmp #152
    bcs @nomove
    sta {{<xpos}}
@nomove:
---
end

system MoveJoyY
    on joyup do with [HasYpos]
---
    lda {{<ypos}}
    sec
    sbc #1
    bcc @nomove
    sta {{<ypos}}
@nomove:
---
    on joydown do with [HasYpos]
---
    lda {{<ypos}}
    clc
    adc #1
    cmp #220
    bcs @nomove
    sta {{<ypos}}
@nomove:
---
end

system SpriteShuffler
	locals 2
	on postframe do select [SpriteSlot]
---
; load two sprite slots at left side of array
	lda {{<SpriteSlot:sprite}}
        sta {{$0}}
	lda {{<SpriteSlot:sprite}}+1
        sta {{$1}}
; move two slots to the left
        ldx #0
@loop:
	lda {{<SpriteSlot:sprite}}+2,x
	sta {{<SpriteSlot:sprite}},x
	inx
        cpx #{{%ecount}}-2
        bne @loop
; store two sprite slots at right side of array
        lda {{$0}}
	sta {{<SpriteSlot:sprite}}+{{%ecount}}-2
        lda {{$1}}
	sta {{<SpriteSlot:sprite}}+{{%ecount}}-1
---
end

system SpriteHider
	locals 1
	on postframe do select [SpriteSlot]
---
	lda #{{%efullcount}}-1
        sta {{$0}}
---
	on postframe do
        join [SpriteSlot]
        with [Sprite,HasYpos]
        limit 2
---
	lda {{<ypos}}
        cmp #192
        bcc @skip
; swap this sprite slot with slot at end of array
	lda {{<SpriteSlot:sprite}},y
        pha
        ldx {{$0}}	; clobbers X, but no longer used
	lda {{<SpriteSlot:sprite}},x
	sta {{<SpriteSlot:sprite}},y
        pla
	sta {{<SpriteSlot:sprite}},x
        dec {{$0}}
@skip:
---
end

///

demo Main

    using FrameLoop, Kernel2Sprite
    using Joystick, MoveJoyX, MoveJoyY
    using SetXPos, SetHorizPos
    using SpriteShuffler, SpriteHider

    entity Kernel [KernelSection, BGColor]
        const lines = 192
        const bgcolor = 0xa2
    end
    
    entity Bitmap1 [Bitmap]
        const bitmapdata = [1, 1, 3, 7, 15, 31, 63, 127]
        const height = 8
    end
    
    entity Bitmap2 [Bitmap]
        const bitmapdata = [$18,$3e,$ff,$ff,$ff,$ff,$3e,$18]
        const height = 8
    end
    
    entity Colormap1 [Colormap]
        const colormapdata = [6, 3, 6, 9, 12, 14, 31, 63]
    end
    
    entity Sprite0 [Sprite,HasBitmap,HasColormap,HasXpos,HasYpos,Player]
        init xpos = 50
        init ypos = 150
        init bitmap = #Bitmap2
        const plyrflags = 0
    end
    
    entity Sprite1 [Sprite,HasBitmap,HasColormap,HasXpos,HasYpos,Player]
        init xpos = 100
        init ypos = 60
        init bitmap = #Bitmap1
        const plyrflags = 3
    end

    entity Sprite2 [Sprite,HasBitmap,HasColormap,HasXpos,HasYpos,Player]
        init xpos = 80
        init ypos = 90
        init bitmap = #Bitmap2
        const plyrflags = 0
    end

    entity Sprite3 [Sprite,HasBitmap,HasColormap,HasXpos,HasYpos,Player]
        init xpos = 40
        init ypos = 150
        init bitmap = #Bitmap1
        const plyrflags = 0
    end
    /*
    entity [Missile,HasXpos,HasYpos]
        init xpos = 70
        init ypos = 70
    end
    */
    entity Slot0 [SpriteSlot]
    	init sprite = #Sprite0
    end
    entity Slot1 [SpriteSlot]
    	init sprite = #Sprite1
    end
    entity Slot2 [SpriteSlot]
    	init sprite = #Sprite2
    end
    entity Slot3 [SpriteSlot]
    	init sprite = #Sprite3
    end

end demo


