                    ORG     $5000

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

                    ;   $FFF8       IRQ Handler
                    ;   $FFF6       FIRQ Handler

                    EXPORT  SET_TIMER_HOOK
                    EXPORT  REMOVE_TIMER_HOOK
                    EXPORT  CAPTURE_PSG_ONESTEP

                    EXPORT  PSGDATAPTR
                    EXPORT  PSGENDPTR

SET_TIMER_HOOK      PSHS    A,B,X,Y,U

                    LEAU    TIMERHOOK,PCR
                    CMPU    $FFF8
                    BEQ     SET_TIMER_HOOK_DONE

                    LDX     $FFF8
                    STX     DEFIRQADDR,PCR

                    STU     $FFF8

                    LEAX    PSGDATA,PCR
                    STX     PSGDATAPTR,PCR
                    STX     PSGENDPTR,PCR

                    LDA     #PSGLASTCMD
                    STA     ,X
                    STA     LASTSTOREDCMD,PCR

                    BSR     READPSG
SET_TIMER_HOOK_DONE
                    PULS    A,B,X,Y,U,PC



REMOVE_TIMER_HOOK   PSHS    A,B,X,Y,U

                    LDX     DEFIRQADDR,PCR
                    STX     $FFF8

                    PULS    A,B,X,Y,U,PC



                    ; Read Reg0 to Reg0d to ,X
READPSG             LDA     #0

READPSG_LOOP        STA     $FD0E       ; PSG Register
                    LDB     #3          ; PSG Register Selection
                    STB     $FD0D
                    CLRB                ; PSG Register Selection end
                    STB     $FD0D       ; Not sure if I can do CLR $FD0D

                    LDB     #1          ; PSG Register Read
                    STB     $FD0D
                    LDB     $FD0E
                    STB     ,X+
                    CLRB                ; PSG Register Read end
                    STB     $FD0D       ; Not sure if I can do CLR $FD0D

                    ; By the way, Register Write is #2

                    INCA
                    CMPA    #13
                    BLE     READPSG_LOOP
                    RTS

REGORDER            FCB     0,1,2,3,4,5,6,7,8,9,$A,$D,$B,$C,$FF

PUSHPSG             LEAX    NEWPSG,PCR
                    LEAY    LASTPSG,PCR
                    LDA     #16
PUSHPSGLOOP
                    LDB     ,X+
                    STB     ,Y+
                    DECA
                    BNE     PUSHPSGLOOP

                    RTS



TIMERHOOK           BSR     CAPTURE_PSG_ONESTEP
                    LDX     DEFIRQADDR,PCR
                    JMP     ,X



CAPTURE_PSG_ONESTEP PSHS    A,B,X,Y,U,CC
                    ORCC    #$50
                    STA     $FD0F

                    LDX     CALLCOUNTER,PCR
                    LEAX    1,X
                    STX     CALLCOUNTER,PCR

                    ; I really want to check if it is from PLAY command.
                    ; But, if I read $FD03, flag looks to be cleared.
;                   LDA     $FD03
;                   BITA    #4
;                   BEQ     NOT_A_TIMER
;
;                   LDX     TIMERCOUNTER,PCR
;                   LEAX    1,X
;                   STX     TIMERCOUNTER,PCR
;
;NOT_A_TIMER
                    BSR     PUSHPSG

                    LEAX    NEWPSG,PCR
                    BSR     READPSG

                    LDX     PSGENDPTR,PCR

                    CLR     REGIDX,PCR
RECORDPSG_ONESTEP_LOOP
                    LDA     REGIDX,PCR
                    LEAU    REGORDER,PCR
                    LDA     A,U

                    LEAU    NEWPSG,PCR
                    LEAY    LASTPSG,PCR

                    LDB     A,U
                    CMPB    A,Y
                    BEQ     RECORDPSG_NOCHANGE
                    STA     ,X+
                    STA     LASTSTOREDCMD,PCR
                    STB     ,X+
RECORDPSG_NOCHANGE
                    INC     REGIDX,PCR
                    LDA     REGIDX,PCR
                    CMPA    #13
                    BLE     RECORDPSG_ONESTEP_LOOP

                    CMPX    PSGENDPTR,PCR
                    BEQ     RECORDPSG_NOCHANGE_FOR_THIS_STEP
        ; Some changes in this step.
                    LDB     #PSGSTEPDIVIDER
                    STB     ,X+
                    STB     LASTSTOREDCMD,PCR
                    LDB     #PSGLASTCMD
                    STB     ,X
                    STX     PSGENDPTR,PCR
                    BRA     RECORDPSG_ENDSTEP

RECORDPSG_NOCHANGE_FOR_THIS_STEP
                    LDA     #PSGNOCHANGE
                    CMPA    LASTSTOREDCMD,PCR
                    BEQ     RECORDPSG_INC_CTR

                    LDB     #PSGSTEPDIVIDER
                    CMPB    LASTSTOREDCMD,PCR
                    BNE     RECORDPSG_NOCHANGE_FOR_THIS_STEP_WRITE
                    CMPB    -1,X    ; Just in case.  Am I that a good programmer?
                    BNE     RECORDPSG_NOCHANGE_FOR_THIS_STEP_WRITE
                    LEAX    -1,X    ; Cancel last divider.

RECORDPSG_NOCHANGE_FOR_THIS_STEP_WRITE
                    STA     ,X+
                    STA     LASTSTOREDCMD,PCR
                    LDB     #1
                    STB     ,X+
                    LDB     #PSGLASTCMD
                    STB     ,X
                    STX     PSGENDPTR,PCR

                    BRA     RECORDPSG_ENDSTEP
RECORDPSG_INC_CTR
                    LDA     -1,X
                    INCA
                    BEQ     RECORDPSG_INC_CTR_OVERFLOW
                    STA     -1,X
                    BRA     RECORDPSG_ENDSTEP

RECORDPSG_INC_CTR_OVERFLOW
                    LDA     #PSGNOCHANGE
                    STA     ,X+
                    STA     LASTSTOREDCMD,PCR
                    LDB     #1
                    STB     ,X+
                    LDB     #PSGLASTCMD
                    STB     ,X
                    STX     PSGENDPTR,PCR

RECORDPSG_ENDSTEP

                    ; To capture re-writing of the same value,
                    ; Reset some registers.
                    ; Do I need to reset these registers every time?
                    ;LDB        #$1F
                    ;LDA        #8
                    ;BSR        WRITE_TO_PSG
                    ;LDA        #9
                    ;BSR        WRITE_TO_PSG
                    ;LDA        #$0A
                    ;BSR        WRITE_TO_PSG
                    ; If register 13(0x0D) is the trigger of the envelope,
                    ; volume registers shouldn't have to be reset for every tone.
                    ; Apparently it's good without re-recording the volume registers.

                    ; If, writing to register 13(0x0D) is the trigger,
                    ; do we need to record all writing to 0B and 0C?
                    ; CLRB
                    ; LDA       #$0B
                    ; BSR       WRITE_TO_PSG
                    ; LDA       #$0C
                    ; BSR       WRITE_TO_PSG
                    ; Looks like I don't need to re-assign 0B and 0C, either.
                    LDB     #$FF
                    LDA     #$0D
                    BSR     WRITE_TO_PSG

                    LEAX    NEWPSG,PCR
                    LBSR    READPSG

                    LDA     $FD0F
                    PULS    A,B,X,Y,U,CC,PC


REGIDX              FCB     0
DEFIRQADDR          FDB     0
CALLCOUNTER         FDB     0
TIMERCOUNTER        FDB     0
TERMINATOR          FDB     $EEFF
PSGDATAPTR          FDB     PSGDATA
PSGENDPTR           FDB     PSGDATA
LASTSTOREDCMD       FCB     0

                    FDB     $8182
NEWPSG              RZB     16
                    FDB     $8384
LASTPSG             RZB     16
                    FDB     $8586

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

                    ORG     $8000
PSGDATA             ; STORE TO URA_RAM

