; For each entry in animationData[], this subroutine uses DMA to copy
; the specified number of bytes from the source address (typically ROM)
; to the VRAM destination address.
;
; This subroutine should be called from the vbi with A=8-bits, X & Y =
; 16-bits.
;
; Each entry in the animationData[] has the following format:
;
; offset (bytes)
;     0..1           VRAM destination address
;     2..4           24-bit source address
;     5..6           number of bytes to copy

processAnimations:
    lda #$80              ; configure VRAM write
    sta $2115

; copy animation data to VRAM
    ldx #$0000

animateLoop:

    cpx animationIndex
    beq doneAnimation

    lda animationData,x   ; get VRAM destination
    inx
    sta $2116
    lda animationData,x
    inx
    sta $2117

    ldy #$1801            ; dma to $2118
    sty $4300

    lda animationData,x   ; get source
    inx
    sta $4302
    lda animationData,x
    inx
    sta $4303
    lda animationData,x
    inx
    sta $4304

    lda animationData,x   ; get number of bytes
    inx
    sta $4305
    lda animationData,x
    inx
    sta $4306

    lda #$01              ; do dma
    sta $420B

    bra animateLoop

doneAnimation:

    ldx.w #$0000
    stx animationIndex

    rts


; This subroutine updates the animationData[] for a 4x4 tile image
; in 16 colours.
;
; The 24-bit address of the tile data should be placed in frameSource,
; i.e. store the 16-bit offset in frameSource and the 8-bit bank number
; in frameSource+$02.
;
; The VRAM destination address should be placed in frameDest.
;
; This subroutine assumes that the source data is stored as 16
; consecutive tiles which form 4 rows of 4 tiles. For the ship frames
; I converted the pcx files with:
;
; pcx2snes -n -s8 -c16 ang_up
;
; In VRAM the tiles are not stored consecutively. A 32x32 sprite with
; tile number 0 will actually use tiles 0..3, 16..19, 32..35 and 48..51.
; Hence the sprite data has to be copied to VRAM in 4 chunks.

update4x4TileFrame:
    rep #$30           ; all 16-bits
    
    ldy #$04           ; loop over 4 rows of tiles
    
    ldx animationIndex ; get current index into animations
    
u32loop
    lda frameDest      ; set VRAM destination
    sta animationData,x
    clc
    adc #$100          ; advance for next row
    sta frameDest
    
    lda frameSource    ; set source address
    sta animationData+$02,x
    clc
    adc #$80           ; advance for next row
    sta frameSource
    
    sep #$20           ; set source address bank
    lda frameSource+$02
    sta animationData+$04,x
    rep #$20
    
    lda #$80           ; copy 4 tiles worth of data (4 x 32 bytes)
    sta animationData+$05,x
    
    txa                ; update index into animations
    clc
    adc #$07
    tax
    
    dey
    bne u32loop
    
    stx animationIndex

    rts


; Set the ship to the frame specified in A.
setShipFrame:
    php
    rep #$30
    
    and #$00FF
    cmp shipFrame     ; check if already set to required frame
    beq sameShipFrame
    
    tax
    stx shipFrame
    lda.l shipFrames,x
    sta frameSource
    lda #$04
    sta frameSource+$02
    lda #$6000
    sta frameDest
    
    jsr update4x4TileFrame 
    
sameShipFrame:
    plp
    rts


.DEFINE NORMAL_SHIP    $00
.DEFINE UP_SHIP        $02
.DEFINE DOWN_SHIP      $04
.DEFINE UP2_SHIP       $06
.DEFINE DOWN2_SHIP     $08

shipFrames:
    .DW ANG_FRAME,ANG_UP_FRAME,ANG_DOWN_FRAME,ANG_UP2_FRAME,ANG_DOWN2_FRAME