                    ORG     $1800

                    BSR     PSGPLAY_SET_IRQ_HOOK
                    BSR     PSGPLAY_START
                    RTS

PSGLASTCMD              EQU     $FF
PSGSTEPDIVIDER          EQU     $FE
PSGNOCHANGE             EQU     $FD     ; Followed by one byte of counter.
PSGBEGINLOOP_INFINITE   EQU     $FC     ; NOT USED YET
PSGBEGINLOOP_FINITE     EQU     $FB     ; NOT USED YET
PSGENDLOOP              EQU     $FA     ; NOT USED YET

                    EXPORT  PSGPLAY_STATE

                    EXPORT  PSGPLAY_SET_IRQ_HOOK
                    EXPORT  PSGPLAY_START
                    EXPORT  PSGPLAY_PAUSE
                    EXPORT  PSGPLAY_REVERT_IRQ_HOOK
                    EXPORT  PSGPLAY_INITPSG
                    EXPORT  INKEY

PSGPLAY_DATAPTR     FDB     $2000
PSGPLAY_CLEAR_AFTER_LAST    FCB     1

PSGPLAY_SET_IRQ_HOOK
                    PSHS    A,B,X,Y,U

                    LEAU    PSGPLAY_IRQHOOK,PCR
                    CMPU    $FFF8
                    BEQ     PSGPLAY_SET_IRQ_HOOK_DONE

                    LDX     $FFF8
                    STX     PSGPLAY_DEFIRQADDR,PCR
                    STU     $FFF8

                    LDX     PSGPLAY_DATAPTR,PCR
                    STX     PSGPLAY_CURRENTPTR,PCR

                    LDA     #STATE_MOVING
                    STA     PSGPLAY_STATE,PCR

                    LBSR    PSGPLAY_INITPSG

PSGPLAY_SET_IRQ_HOOK_DONE
                    PULS    A,B,X,Y,U,PC



PSGPLAY_REVERT_IRQ_HOOK
                    PSHS    X
                    BSR     PSGPLAY_PAUSE
                    LDX     PSGPLAY_DEFIRQADDR,PCR
                    STX     $FFF8
                    PULS    X,PC



PSGPLAY_START       PSHS    A,B
                    LDA     #4
                    STA     $FD02
                    PULS    A,B,PC



PSGPLAY_PAUSE       PSHS    A,B
                    LDA     #0
                    STA     $FD02
                    PULS    A,B,PC


LAST_KEYCODE        FCB     0

                    ; Returns the last key stroke in A register.
INKEY               LDA     LAST_KEYCODE,PCR
                    CLR     LAST_KEYCODE,PCR
                    RTS



NOT_A_TIMER_OR_KEY  LDX     PSGPLAY_DEFIRQADDR,PCR
                    JMP     ,X

HANDLE_KEY_IRQ      LDA     $FD01
                    STA     LAST_KEYCODE,PCR
                    RTI

PSGPLAY_IRQHOOK     LDA     $FD03
                    BITA    #1
                    BEQ     HANDLE_KEY_IRQ
                    BITA    #4
                    BNE     NOT_A_TIMER_OR_KEY

                    ORCC    #$50
                    STA     $FD0F   ; URA-RAM On

                    LDA     PSGPLAY_STATE,PCR
                    CMPA    #STATE_MOVING
                    BEQ     PSGPLAY_IRQHOOK_MOVEFORWARD
                    CMPA    #STATE_WAITING
                    BEQ     PSGPLAY_IRQHOOK_WAITING

                    TST     PSGPLAY_CLEAR_AFTER_LAST,PCR
                    BEQ     PSGPLAY_AUTO_RESET_DONE

                    ; Auto clear IRQ hooks
                    LBSR    PSGPLAY_REVERT_IRQ_HOOK
                    LBSR    PSGPLAY_INITPSG
PSGPLAY_AUTO_RESET_DONE
                    BRA     PSGPLAY_IRQHOOK_END

PSGPLAY_IRQHOOK_WAITING
                    LDD     PSGPLAY_WAITCOUNT,PCR
                    SUBD    #1
                    STD     PSGPLAY_WAITCOUNT,PCR
                    BNE     PSGPLAY_IRQHOOK_END
                    LDA     #STATE_MOVING
                    STA     PSGPLAY_STATE,PCR
                    BRA     PSGPLAY_IRQHOOK_END

PSGPLAY_IRQHOOK_MOVEFORWARD
                    LDX     PSGPLAY_CURRENTPTR,PCR

PSGPLAY_IRQHOOK_MOVEFORWARD_LOOP
                    LDA     ,X+
                    CMPA    #PSGLASTCMD
                    BEQ     PSGPLAY_IRQHOOK_MOVEDFORWARD_LASTCMD
                    CMPA    #PSGSTEPDIVIDER
                    BEQ     PSGPLAY_IRQHOOK_MOVEDFORWARD
                    CMPA    #PSGNOCHANGE
                    BEQ     PSGPLAY_IRQHOOK_MOVEDFORWARD_NOCHANGE
                    CMPA    #13
                    BHI     PSGPLAY_IRQHOOK_MOVEDFORWARD_LASTCMD ; Fatal error.

                    LDB     ,X+
                    BSR     WRITE_TO_PSG

                    BRA     PSGPLAY_IRQHOOK_MOVEFORWARD_LOOP

PSGPLAY_IRQHOOK_MOVEDFORWARD_LASTCMD
                    LDA     #STATE_DONE
                    STA     PSGPLAY_STATE,PCR
                    BRA     PSGPLAY_IRQHOOK_END

PSGPLAY_IRQHOOK_MOVEDFORWARD_NOCHANGE
                    CLRA
                    LDB     ,X+
                    STD     PSGPLAY_WAITCOUNT,PCR
                    LDA     #STATE_WAITING
                    STA     PSGPLAY_STATE,PCR
                    BRA     PSGPLAY_IRQHOOK_MOVEDFORWARD

PSGPLAY_IRQHOOK_MOVEDFORWARD
                    STX     PSGPLAY_CURRENTPTR,PCR
                    BRA     PSGPLAY_IRQHOOK_END

PSGPLAY_IRQHOOK_END
                    LDA     $FD0F   ; URA-RAM Off
                    ANDCC   #$50
                    RTI



STATE_MOVING        EQU     0
STATE_WAITING       EQU     1
STATE_DONE          EQU     2

PSGPLAY_STATE       FCB     0
PSGPLAY_WAITCOUNT   FDB     0
PSGPLAY_CURRENTPTR  FDB     0
PSGPLAY_DEFIRQADDR  FDB     0

WRITE_TO_PSG        PSHS    A,B
                    STA     $FD0E       ; PSG Register
                    LDA     #3          ; PSG Register Selection
                    STA     $FD0D
                    CLR     $FD0D       ; PSG Register Selection end

                    STB     $FD0E
                    LDA     #2          ; PSG Write
                    STA     $FD0D
                    CLR     $FD0D
                    PULS    A,B,PC



PSGPLAY_INITPSG     PSHS    A,B
                    LDA     #$0D
                    CLRB
PSGPLAY_INITPSG_LOOP
                    BSR     WRITE_TO_PSG
                    DECA
                    BPL     PSGPLAY_INITPSG_LOOP

                    LDA     #7
                    LDB     #$F8
                    BSR     WRITE_TO_PSG
                    PULS    A,B,PC
