/*
 * This file is part of libsidplayfp, a SID player engine.
 *
 * Copyright 2014 Leandro Nini <drfiemost@users.sourceforge.net>
 * Copyright 2001-2004 Simon White
 * Copyright 2000 Dag Lem
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */


/***************************************************************************
 * psiddrv.a65  -  C64 Sid Player
 * 
 * written by Dag Lem
 * modified by Simon White for use in the sidplayer SIDPlay2.
 * 
 * Build with:
 * xa -R -G psiddrv.a65 -o psiddrv.o65
 * od -v -An -w8 -tx1 psiddrv.o65 | sed -re 's/[[:alnum:]]+/0x&,/g' > psiddrv.bin
 ***************************************************************************/

            ; entry address
coldvec     .word cold

            ; initial user interrupt vectors
irqusr      .word irqret
            ; These should never run
brkusr      .word exception
nmiusr      .word exception

            ; redirect basic restart vector
            ; to finish the init sequence
            ; (hooks in via stop function)
stopusr     .word setiomap

playnum     .byte 0
speed       .byte 0
initvec     .word 0
playvec     .word 0
initiomap   .byte 0
playiomap   .byte 0
video       .byte 0
clock       .byte 0
flags       .byte 0

            ; init/play PSID
play        jmp (playvec)
init        jmp (initvec)

            ; cold start
cold        sei

            ; turn interrupts off and
            ; clear any pending irqs
            lda #$00
            sta $d01a
            lda $d019
            sta $d019
            lda #$7f
            sta $dc0d
            sta $dd0d
            lda $dc0d
            lda $dd0d

            ; setup hardware

            ; maximum volume
            lda #$0f
            sta $d418

            ; set CIA 1 Timer A to 50/60 Hz
            lda video
            beq ntsc
pal         ldx #$25
            ldy #$40
            jmp timer
ntsc        ldx #$95
            ldy #$42
timer       stx $dc04
            sty $dc05

            ; set VICII raster to line 311 for RSIDs
            ldx #$9b
            ldy #$37

            ; we should use the proper values for
            ; the default raster, however if the tune
            ; is playing at the wrong speed (e.g.
            ; PAL at NTSC) use the compatibility
            ; raster instead to try make it work
            eor clock
            ora initiomap
            beq vicinit

            ; set VICII raster to line 0 for PSIDs
            ; (compatibility raster)
            ldx #$1b
            ldy #$00
vicinit     stx $d011
            sty $d012

            ; don't override default irq handler for RSIDs
            lda initiomap
            beq irqinit

            ; if play address, override default irq vector so
            ; we reach our routine to handle play routine
            lda playiomap
            beq irqinit
            ldx #<irqjob
            stx $0314

            ; 0 indicates VIC timing (PSIDs only)
            ; else it's from CIA
irqinit     lda speed
            bne ciainit

            ; enable VICII raster interrupt
            lda #$81
            sta $d01a
            jmp setiomap

            ; enable CIA 1 timer A interrupt
ciainit     lda #$81
            ldx #$01
            sta $dc0d
            stx $dc0e

            ; set I/O map and call song init routine
setiomap    lda initiomap
            bne setbank

            ; only release interrupt mask for real
            ; C64 tunes (initiomap = 0) thus
            ; providing a more realistic environment
            lda #$37
setbank     sta $01

setregs     lda flags
            pha
            lda playnum
            plp
            jsr init
            lda initiomap
            beq idle
            lda playiomap
            beq run
            lda #$37
            sta $01

run         cli
idle        jmp idle

irqjob      lda $01
            pha
            lda playiomap
            sta $01
            lda #0
            jsr play
            pla
            sta $01
            dec $d019
irqret      lda $dc0d
            pla
            tay
            pla
            tax
            pla
            rti

            ; HLT
exception   .byte $02

.end
