; Oct 3th '04: Added bugfix for song download [dr. sloppy]



; audio definitions

.DEFINE APU_PORT0 $2140
.DEFINE APU_PORT1 $2141
.DEFINE APU_PORT2 $2142
.DEFINE APU_PORT3 $2143

.DEFINE SPC_SOURCE $00

.DEFINE MUSIC_ONLY_ENABLED $01
.DEFINE ALL_AUDIO_ENABLED  $07

; songs
.DEFINE NO_SONG      $00
.DEFINE SONG_ASCHE   $01
.DEFINE SONG_ATOMIC  $02
.DEFINE SONG_AWOLF   $03
.DEFINE SONG_AXELAY  $04
.DEFINE SONG_BOWSER  $05
.DEFINE SONG_C1GO    $06
.DEFINE SONG_C2G0    $07
.DEFINE SONG_GRADIUS $08
.DEFINE SONG_ICE     $09
.DEFINE SONG_LUIGI   $0A
.DEFINE SONG_SPOOKIE $0B
.DEFINE SONG_UNSQUAD $0C
.DEFINE SONG_XENON   $0D
.DEFINE SONG_GOKU    $0E
.DEFINE SONG_MERRY   $0F
.DEFINE SONG_METLM   $10
.DEFINE SONG_SEASIA  $11
.DEFINE SONG_RUD21   $12
.DEFINE SONG_FZERO   $13
.DEFINE SONG_GOOP    $14
.DEFINE SONG_SHERB   $15
.DEFINE SONG_PENNY   $16

; voice 0 sfx
.DEFINE V0SFX_EXPLOSION    $04
.DEFINE V0SFX_GUN_FIRE     $05
.DEFINE V0SFX_GLASS_SMASH  $06
.DEFINE V0SFX_INTERFERENCE $07
.DEFINE V0SFX_DEEP_THUMP   $08

; voice 1 sfx
.DEFINE V1SFX_PING_HIGH        $09
.DEFINE V1SFX_PING_LOW         $0A
.DEFINE V1SFX_DING_A_LING_HIGH $0B
.DEFINE V1SFX_DING_A_LING_LOW  $0C
.DEFINE V1SFX_LASER_FIRE       $0D
.DEFINE V1SFX_SQUISH           $0E

    
; download program to SPC, the 24-bit address of the audio data
; should be stored in location SPC_SOURCE
AUDIO_BOOT:
    php

    rep #$30
    ldy #$0000
    lda.w #$BBAA

boot_initial:
    cmp APU_PORT0
    bne boot_initial

    sep #$20
    lda #$CC
    bra boot_entry1

boot_repeat:
    lda [SPC_SOURCE],y
    iny
    xba
    lda #$00
    bra boot_entry2

boot_loop:
    xba
    lda [SPC_SOURCE],y
    iny

    cpy.w #$8000
    bne boot_skip_1

    inc SPC_SOURCE+$02
    ldy #$0000

boot_skip_1:

    xba

boot_wait1:
    cmp APU_PORT0
    bne boot_wait1

    inc a

boot_entry2:
    rep #$20
    sta APU_PORT0

    sep #$20
    dex
    bne boot_loop

boot_wait2:
    cmp APU_PORT0
    bne boot_wait2

boot_zero:
    adc #$03
    beq boot_zero

boot_entry1:
    pha

    rep #$20
    lda [SPC_SOURCE],y
    iny
    iny
    tax
    lda [SPC_SOURCE],y
    iny
    iny
    sta APU_PORT2

    sep #$20
    cpx.w #$0001
    lda #$00
    rol
    sta APU_PORT1
    adc #$7F
    pla
    sta APU_PORT0

boot_wait3:
    cmp APU_PORT0
    bne boot_wait3

    bvs boot_repeat

    plp

    rts

; when calling all subroutines below, A must be 8-bits

; play a voice 0 sound effect
AUDIO_PLAY_V0SFX:
  sta APU_PORT1
  rts

; play a voice 1 sound effect
AUDIO_PLAY_V1SFX:
  sta APU_PORT2
  rts

; configure audio
AUDIO_CONTROL:
  sta APU_PORT3
  cmp APU_PORT3
  bne AUDIO_CONTROL
  rts

SONG_TABLE:
    ;   offset       bank  length                         play once only
    ;   ------       ----  ------                         --------------
    ;
    .DW ASCHE_MUS,   $06,  ASCHE_MUS_END   - ASCHE_MUS,   $00
    .DW ATOMIC_MUS,  $06,  ATOMIC_MUS_END  - ATOMIC_MUS,  $00
    .DW AWOLF_MUS,   $06,  AWOLF_MUS_END   - AWOLF_MUS,   $00
    .DW AXELAY_MUS,  $06,  AXELAY_MUS_END  - AXELAY_MUS,  $00
    .DW BOWSER_MUS,  $06,  BOWSER_MUS_END  - BOWSER_MUS,  $00
    .DW C1GO_MUS,    $06,  C1GO_MUS_END    - C1GO_MUS,    $01
    .DW C2G0_MUS,    $06,  C2G0_MUS_END    - C2G0_MUS,    $01
    .DW GRADIUS_MUS, $06,  GRADIUS_MUS_END - GRADIUS_MUS, $00
    .DW ICE_MUS,     $06,  ICE_MUS_END     - ICE_MUS,     $00
    .DW LUIGI_MUS,   $06,  LUIGI_MUS_END   - LUIGI_MUS,   $00
    .DW SPOOKIE_MUS, $06,  SPOOKIE_MUS_END - SPOOKIE_MUS, $00
    .DW UNSQUAD_MUS, $06,  UNSQUAD_MUS_END - UNSQUAD_MUS, $00
    .DW XENON_MUS,   $06,  XENON_MUS_END   - XENON_MUS,   $00
    .DW GOKU_MUS,    $07,  GOKU_MUS_END    - GOKU_MUS,    $00
    .DW MERRY_MUS,   $07,  MERRY_MUS_END   - MERRY_MUS,   $00
    .DW METLM_MUS,   $07,  METLM_MUS_END   - METLM_MUS,   $00
    .DW SEASIA_MUS,  $07,  SEASIA_MUS_END  - SEASIA_MUS,  $00
    .DW RUD21_MUS,   $07,  RUD21_MUS_END   - RUD21_MUS,   $00
    .DW FZERO_MUS,   $07,  FZERO_MUS_END   - FZERO_MUS,   $00
    .DW GOOP_MUS,    $08,  GOOP_MUS_END    - GOOP_MUS,    $00
    .DW SHERB_MUS,   $08,  SHERB_MUS_END   - SHERB_MUS,   $00
    .DW PENNY_MUS,   $09,  PENNY_MUS_END   - PENNY_MUS,   $00

AUDIO_PLAY_SONG
    php
    
    sep #$20
    
    pha
    
    ; cancel any previous song
    lda #$01
    jsr play_song
    
    pla

    cmp #$01
    bmi aps_skip1

    ; formulate index into SONG_TABLE
    dec a
    rep #$30
    and #$00FF
    asl
    asl
    asl
    tax

    ; get offset from SONG_TABLE
    lda.w SONG_TABLE,x
    sta.b SPC_SOURCE
    
    ; get bank from SONG_TABLE
    sep #$20
    lda.w SONG_TABLE+$02,x
    sta.b SPC_SOURCE+$02

    ; get play once indication from SONG_TABLE
    lda.w SONG_TABLE+$06,x
    inc a
    inc a
    pha

    ; get length from SONG_TABLE
    rep #$20
    lda.w SONG_TABLE+$04,x
    tax

    ; request song download
    sep #$20
ads_letsRetry
    lda #-42
    sta APU_PORT0

    ; wait for ack
    phx
    ldx #$FF
ads_loop1
    lda APU_PORT0
    cmp #$FF
    beq ads_skip2
    dex
    bne ads_loop1

    ; BUGFIX
    ; things probably went bad rather bad since we've ended up here,
    ; therefore we'll just try again and again until success :)
    plx
    jmp ads_letsRetry

ads_skip2
    plx
    
    ; write song data to SPC
    ldy #0
ads_loop2:
    lda [SPC_SOURCE],y
    jsr audio_write_byte
    iny
    dex
    bne ads_loop2

    ; play downloaded song
    pla
    jsr play_song
    
aps_skip1:
    plp
    rts

play_song:
  phx
  ldx #$FF
  
ps_loop1
  sta APU_PORT0
  cmp APU_PORT0
  beq ps_skip1
  dex
  bne ps_loop1
  
ps_skip1
  plx
  rts

audio_write_byte
  phx

awb_retry1
  ; send byte to SPC
  sta APU_PORT0

  ; wait for ack
  ldx #$FF
awb_loop1
  cmp APU_PORT0
  beq awb_skip1
  dex
  bne awb_loop1
;  bra awb_retry1

awb_skip1
  ; ack
  lda #$FF
  sta APU_PORT0
  
  ; wait for ack
  ldx #$FF
awb_loop2
  cmp APU_PORT0
  beq awb_skip2
  dex
  bne awb_loop2
;  bra awb_skip1
  
awb_skip2

  plx

  rts
