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	PSGPLAY_DATAPTR
					EXPORT	PSGPLAY_CURRENTPTR
					EXPORT	PSGPLAY_10MS_TICK
					EXPORT	PSGPLAY_GET_COUNTER
					EXPORT	INKEY

PSGPLAY_DATAPTR		FDB		$2000
PSGPLAY_CLEAR_AFTER_LAST	FCB		1
PSGPLAY_10MS_TICK	FDB		0
PSGPLAY_5TICK		FCB		0

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
					LDD		#0
					STD		PSGPLAY_10MS_TICK,PCR
					STA		PSGPLAY_5TICK,PCR

					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


					INC		PSGPLAY_5TICK,PCR
					LDA		PSGPLAY_5TICK,PCR
					CMPA	#5
					BCS		PSGPLAY_IRQHOOK_PASSED_5TICK

					CLR		PSGPLAY_5TICK,PCR
					LDD		PSGPLAY_10MS_TICK,PCR
					ADDD	#1
					STD		PSGPLAY_10MS_TICK,PCR

PSGPLAY_IRQHOOK_PASSED_5TICK
					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



PSGPLAY_GET_COUNTER
					LDD		PSGPLAY_CURRENTPTR,PCR
					CMPD	PSGPLAY_CURRENTPTR,PCR
					BNE		PSGPLAY_GET_COUNTER		; Make sure the counter didn't change between LDD and CMPD.  IRQ may fire anytime.
					SUBD	PSGPLAY_DATAPTR,PCR
					RTS



PSGPLAY_GET_10MS_TICK
					LDD		PSGPLAY_10MS_TICK,PCR
					CMPD	PSGPLAY_10MS_TICK,PCR
					BNE		PSGPLAY_GET_10MS_TICK
					RTS
