.DEFINE windowPositions $7FF000
.DEFINE hdmaPointer     $00
.DEFINE count           hdmaPointer+$03
.DEFINE delay           count+$01
.DEFINE fadeCount       delay+$02


; circle fade out, inside window
circleFadeOut_inside
    php
    
    wai            ; wait for vertical blank
    
    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #circle_data_1&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_1
    sta.b hdmaPointer+$02
    
    ; perform fade out
    jsr insideFadeOut
    
    plp
    rts


; circle fade out, outside window
circleFadeOut_outside
    php

    wai            ; wait for vertical blank

    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #circle_data_2&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_1
    sta.b hdmaPointer+$02
    
    ; perform fade out
    jsr outsideFadeOut
    
    plp
    rts


; triange fade out, inside window
triangleFadeOut_inside
    php

    wai            ; wait for vertical blank
    
    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #triangle_data&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_1
    sta.b hdmaPointer+$02
    
    ; perform fade out
    jsr insideFadeOut
    
    plp
    rts


; square fade out, inside window
squareFadeOut_inside
    php
    
    wai            ; wait for vertical blank

    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #square_data_1&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_2
    sta.b hdmaPointer+$02
    
    ; perform fade out
    jsr insideFadeOut
    
    plp
    rts


; square fade out, outside window
squareFadeOut_outside
    php
    
    wai            ; wait for vertical blank

    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #square_data_2&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_2
    sta.b hdmaPointer+$02
    
    ; perform fade out
    jsr outsideFadeOut
    
    plp
    rts


; circle fade in, inside window
circleFadeIn_inside
    php

    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #circle_data_2&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_1
    sta.b hdmaPointer+$02
    
    ; perform fade in
    jsr insideFadeIn
    
    plp
    rts


; circle fade in, outside window
circleFadeIn_outside
    php

    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #circle_data_1&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_1
    sta.b hdmaPointer+$02
    
    ; perform fade in
    jsr outsideFadeIn
    
    plp
    rts


; triangle fade in, outside window
triangleFadeIn_outside
    php

    jsr initFade
    
    ; set pointers to triangle fade data
    lda.w #triangle_data&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_1
    sta.b hdmaPointer+$02
    
    ; perform fade in
    jsr outsideFadeIn
    
    plp
    rts


; square fade in, inside window
squareFadeIn_inside
    php

    jsr initFade
    
    ; set pointers to circle fade data
    lda.w #square_data_2&$FFFF
    sta.b hdmaPointer
    sep #$20       ; A 8-bits
    lda #FADE_BANK_2
    sta.b hdmaPointer+$02
    
    ; perform fade in
    jsr insideFadeIn
    
    plp
    rts


initFade

    sep #$20       ; A 8-bits

    stz $2125      ; disable colour window
    lda #$30
    sta $2130
    stz $2131

    rep #$20       ; A 16-bits
    
    rts


; inside window fade out
insideFadeOut
    php
    sep #$20        ; A 8-bits

    wai             ; wait for vertical blank

    lda #$33        ; enable window
    sta $2123
    lda #$03
    sta $2124
    lda #$03
    sta $2125
ifo_rejoin
    lda #$17
    sta $212E

; configure horizontal dma
    lda #$01        ; 2 address format
    sta $4310
    lda #$26        ; window positions at $2126
    sta $4311
    ldx.w #windowPositions&$FFFF ; hdma list location
    stx $4312
    lda #windowPositions/$10000 ; hdma list bank
    sta $4314

    lda [hdmaPointer] ; set vb delay between fade out frames
    sta.b delay

    ldy #$0001      ; configure hdma data for first frame
    jsr configureWindowHdmaData

    lda #$02        ; enable hdma channel 2
    sta $420c

ifo_loop
    lda #$00        ; frame delay

ifo_delay
    wai             ; wait for vertical blank
    clc
    adc #$01
    cmp.b delay
    bmi ifo_delay

; configure hdma data for next frame
    jsr configureWindowHdmaData

    cpx.w #$0000    ; check for finish
    bne ifo_loop

    lda #$00        ; disable hdma channel 1
    sta $420c

    stz $2123       ; disable window
    stz $2124
    stz $2125
    stz $212E
    lda #$80        ; disable screen
    sta $2100
    lda #$00        ; disable vbi and joypad read
    sta $4200
    sei             ; halt interrupts

    plp
    rts


; outside window fade out
outsideFadeOut
    php
    sep #$20        ; A 8-bits

    wai             ; wait for vertical blank

    lda #$22        ; enable window
    sta $2123
    lda #$02
    sta $2124
    lda #$02
    sta $2125

    jmp ifo_rejoin


; outside window fade in
outsideFadeIn
    php
    sep #$20        ; A 8-bits

    lda #$00        ; enable screen, brightness off
    sta $2100
    lda #$81        ; enable vbi and joypad read
    sta $4200
    cli             ; enable interrupts

    wai             ; wait for vertical blank

    lda #$22        ; enable window
    sta $2123
    lda #$02
    sta $2124
    lda #$02
    sta $2125
ofi_rejoin
    lda #$17
    sta $212E

; configure horizontal dma
    lda #$01        ; 2 address format
    sta $4310
    lda #$26        ; window positions at $2126
    sta $4311
    ldx.w #windowPositions&$FFFF ; hdma list location
    stx $4312
    lda #windowPositions/$10000 ; hdma list bank
    sta $4314

    lda [hdmaPointer] ; set vb delay between fade out frames
    sta.b delay

    ldy #$0001      ; configure hdma data for first frame
    jsr configureWindowHdmaData

    lda #$02        ; enable hdma channel 2
    sta $420c

    lda #$0F        ; full brightness
    sta $2100

ofi_loop
    lda #$00        ; frame delay

ofi_delay
    wai             ; wait for vertical blank
    clc
    adc #$01
    cmp.b delay
    bmi ofi_delay

; configure hdma data for next frame
    jsr configureWindowHdmaData

    cpx.w #$0000    ; check for finish
    bne ofi_loop

    lda #$00        ; disable hdma channel 1
    sta $420c

    stz $2123       ; disable window
    stz $2124
    stz $2125
    stz $212E

    plp
    rts


; inside window fade in
insideFadeIn
    php
    sep #$20        ; A 8-bits

    lda #$00        ; enable screen, brightness off
    sta $2100
    lda #$81        ; enable vbi and joypad read
    sta $4200
    cli             ; enable interrupts

    wai             ; wait for vertical blank

    lda #$33        ; enable window
    sta $2123
    lda #$03
    sta $2124
    lda #$03
    sta $2125

    jmp ofi_rejoin


; read hdma data from ROM and store it in RAM
configureWindowHdmaData
    ldx.w #$0000    ; index into destination RAM

cwhd_mainLoop
    lda [hdmaPointer],y ; get next byte from source ROM
    beq cwhd_done   ; termination byte?
    bpl cwhd_repeat ; repeat byte?

cwhd_string         ; otherwise string of bytes
    iny
    sta.l windowPositions,x ; write byte to destination RAM
    inx

    and #$7F        ; mask off string bit and store count
    sta.b count

cwhd_copyLoop
    lda [hdmaPointer],y ; get 2 bytes from ROM and store in RAM
    iny
    sta.l windowPositions,x
    inx
    lda [hdmaPointer],y
    iny
    sta.l windowPositions,x
    inx

    dec.b count     ; repeat for count
    bne cwhd_copyLoop

    bra cwhd_mainLoop

cwhd_done           ; end of data
    iny
    sta.l windowPositions,x
    rts

cwhd_repeat         ; repeated bytes
    iny
    sta.l windowPositions,x ; write byte to destination RAM
    inx

    lda [hdmaPointer],y ; get 2 bytes from ROM and store in RAM
    iny
    sta.l windowPositions,x
    inx
    lda [hdmaPointer],y
    iny
    sta.l windowPositions,x
    inx

    bra cwhd_mainLoop
