;============================================================
	DEVICE ZXSPECTRUM128
;============================================================
ORG_PLAYER	EQU	#C000
ORG_TBL		EQU	#C200
ORG_TRACK	EQU	#D000
ORG_PATT	EQU	#D066
;-------
PATTSIZE	EQU	192	;размер паттерна (block_size)
CHA_TYPE 	EQU	0	;Тип канала A
CHB_TYPE 	EQU	0	;Тип канала B	;0-громкость в таблице
CHC_TYPE 	EQU	0	;Тип канала C	;1-громкость в паттерне
;-------
PL_CONST_T	EQU	1	;Тип плеера: 0-простой, 1-фиксированный по тактам
PL_LOOPFLAG	EQU	1	;Зацикливание 0-не надо, 1-надо зацикливать
PL_LOOP		EQU	0	;адрес в треке для зацикливания
;-------
TBL_NV_A	EQU	#C200
TBL_NV_B	EQU	#C500
TBL_NV_C	EQU	#C800
TBL_ENV		EQU	#CB00
TBL_REG		EQU	#CE00
;----------------------------
	ORG	ORG_PLAYER
;----------------------------
; CALL PLAYER - инициализация (без проигрывания)
; CALL PLAYER+3 - проигрывание
; Проигрывание, без смены паттерна = 964..997t, со сменой = 1172..1201t
;					со сменой и зацикливанием = + 24..50t
; Используемые регистры: BC,BC`,AF,HL',DE'

PLAYER	JP	INIT
	LD	BC,#BFFD	;10
	EXX			;4
	LD	BC,#FFFD	;10 //24
	//--- read data	-------------------------------	Channel_A
	LD	HL,0		;10
ADR_A	EQU	$-2
	LD	E,(HL)		;7
	INC	HL		;6
	LD	D,TBL_NV_A/256	;7 //30
	//--- out data
	XOR	A	;4	out_reg_0
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4
	INC	D	;4
	LD	A,1	;7	out_reg_1
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //93
	//---
	IF CHA_TYPE=0
	INC	D	;4	out_reg_8
	LD	A,8	;7
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //50
	ENDIF
	//---
	IF CHA_TYPE=1
	LD	A,8	;7	out_reg_8
	OUT	(C),A	;12
	LD	A,(HL)	;7
	INC	HL	;6
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //52
	ENDIF
	//---
	LD	(ADR_A),HL ;16 ///189 or 191
	//--- read data	-------------------------------	Channel_B
	LD	HL,0		;10
ADR_B	EQU	$-2
	LD	E,(HL)		;7
	INC	HL		;6
	LD	D,TBL_NV_B/256	;7 //30
	//--- out data
	LD	A,2	;7	out_reg_2
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4
	INC	D	;4
	LD	A,3	;7	out_reg_3
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //96
	//---
	IF CHB_TYPE=0
	INC	D	;4	out_reg_9
	LD	A,9	;7
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //50
	ENDIF
	//---
	IF CHB_TYPE=1
	LD	A,9	;7	out_reg_9
	OUT	(C),A	;12
	LD	A,(HL)	;7
	INC	HL	;6
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //52
	ENDIF
	//---
	LD	(ADR_B),HL ;16 ///192 or 194
	//--- read data	-------------------------------	Channel_C
	LD	HL,0		;10
ADR_C	EQU	$-2
	LD	E,(HL)		;7
	INC	HL		;6
	LD	D,TBL_NV_C/256	;7 //30
	//--- out data
	LD	A,4	;7	out_reg_4
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4
	INC	D	;4
	LD	A,5	;4	out_reg_5
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //96
	//---
	IF CHC_TYPE=0
	INC	D	;4	out_reg_10
	LD	A,10	;7
	OUT	(C),A	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //50
	ENDIF
	//---
	IF CHC_TYPE=1
	LD	A,10	;7	out_reg_10
	OUT	(C),A	;12
	LD	A,(HL)	;7
	INC	HL	;6
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //52
	ENDIF
	//---
	LD	(ADR_C),HL ;16 ///192 or 194
	//--- read data	-------------------------------	Channel_Env
	LD	HL,0		;10
ADR_E	EQU	$-2
	LD	E,(HL)		;7
	INC	HL		;6
	LD	(ADR_E),HL	;16
	EX	DE,HL		;4
	LD	H,TBL_ENV/256	;7 //50
	//--- out data
	LD	E,11	;7	out_reg_11
	OUT	(C),E	;12
	LD	A,(HL)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4
	INC	H	;4 //50
	//---
	INC	E	;4	out_reg_12
	OUT	(C),E	;12
	LD	A,(HL)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4
	INC	H	;4 //47
	//---
	INC	E	;4
	OUT	(C),E	;12	out_reg_13
	IN	A,(C)	;12
	CP	(HL)	;7
	//-----------
	IF PL_CONST_T=0
		JP	Z,NO13	;10 /45
		;--
		LD	A,(HL)	;7
		EXX		;4
		OUT	(C),A	;12
		EXX		;4 /27 //45..72
NO13		;--		///192..219t variable
	ENDIF
	//-----------
	IF PL_CONST_T=1
		JP	NZ,YES13 ;10 /45
		;--
		LD	A,0	;7
		LD	HL,0	;10
		JP	NO13	;10 /27
YES13		;--
		LD	A,(HL)	;7
		EXX		;4
		OUT	(C),A	;12
		EXX		;4 /27 //72
NO13		;--		///219t fixed
	ENDIF
	//--- read data	-------------------------------	Channel_Reg
	LD	HL,0		;10
ADR_R	EQU	$-2
	LD	E,(HL)		;7
	INC	HL		;6
	LD	(ADR_R),HL	;16
	LD	D,TBL_REG/256	;7 //46
	//--- out data
	LD	L,6	;7	out_reg_6 (noise)
	OUT	(C),L	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4
	INC	D	;4 //50
	//---
	INC	L	;4	out_reg_7 (control)
	OUT	(C),L	;12
	LD	A,(DE)	;7
	EXX		;4
	OUT	(C),A	;12
	EXX		;4 //43 ///139
	//--- вывод в регистры закончен, проверяем конец паттерна
	LD	HL,CURRPOS	;10
	DEC	(HL)		;11
	//------
	IF PL_CONST_T=0
		JP	NZ,P_RET	;10 //31
	ENDIF
	//------
	IF PL_CONST_T=1 AND PL_LOOPFLAG=0
		JP	Z,NEXT_P ;10 //31
		;-
		LD	A,12
		DEC	A
		JP	NZ,$-1
		LD A,0:NOP:NOP:NOP ;19
		;-
		JP	P_RET	;10
	ENDIF
	//------
	IF PL_CONST_T=1 AND PL_LOOPFLAG=1
		JP	Z,NEXT_P ;10 //31
		;-
		LD	A,16
		DEC	A
		JP	NZ,$-1
		LD A,0:DEC HL ;13
		;-
		JP	P_RET	;10
	ENDIF
				;нет конца паттера //24+3*(189..191)+(189..216)+139+31+14
				; t=964..997 (no pattern change)
NEXT_P	//--- переход на новый паттерн
	LD	A,PATTSIZE	;7
	LD	(HL),A		;7
	LD	(PLAY_SP),SP	;20
	LD	SP,0		;10
ADR_PATT EQU	$-2
	POP	HL		;10
	LD	(ADR_A),HL	;16
	POP	HL		;10
	LD	(ADR_B),HL	;16
	POP	HL		;10
	LD	(ADR_C),HL	;16
	POP	HL		;10
	LD	(ADR_E),HL	;16
	POP	HL		;10
	LD	(ADR_R),HL	;16
	LD	(ADR_PATT),SP	;20 //194 (+return 24t)
				; t=1168..1201 (with pattern change)
//---------------------------------
//--- LOOPER
//---------------------------------
	IF PL_LOOPFLAG=1 AND PL_CONST_T=0
		POP	AF		;10
		OR	A		;4
		JP	NZ,NOLP		;10
		LD	HL,BEGIN_TRACK	;10
		LD	(ADR_PATT),HL	;16 //24..50
NOLP		;--
	ENDIF
//---------------------------------
//--- LOOPER CONST T
//---------------------------------
	IF PL_LOOPFLAG=1 AND PL_CONST_T=1
		POP	AF		;10
		OR	A		;4
		JP	Z,YESLP		;10
		NOP:NOP:NOP:NOP	;16
		JP	NOLP	;10
YESLP		LD	HL,BEGIN_TRACK	;10
		LD	(ADR_PATT),HL	;16 //50
NOLP		;--
	ENDIF
//---------------------------------
//--- RETURN FROM PLAYER (24t)
//---------------------------------
	LD	SP,0		;10
PLAY_SP	EQU	$-2
P_RET	EXX			;4
	RET			;10 //24	;t=1172..1259
//---------------------------------
INIT	LD	C,#FD
	LD	DE,#BFFF
	LD	HL,#000D
INIT_B1	LD	B,E
	OUT	(C),L
	LD	B,D
	OUT	(C),H
	DEC	L
	JP	P,INIT_B1
	;--
	LD	(PLAYiSP),SP	;20
	LD	SP,BEGIN_TRACK	;10
	POP	HL		;10
	LD	(ADR_A),HL	;16
	POP	HL		;10
	LD	(ADR_B),HL	;16
	POP	HL		;10
	LD	(ADR_C),HL	;16
	POP	HL		;10
	LD	(ADR_E),HL	;16
	POP	HL		;10
	LD	(ADR_R),HL	;16
	LD	(ADR_PATT),SP	;20
	LD	SP,0		;10
PLAYiSP	EQU	$-2
	;--
	LD	A,PATTSIZE
	LD	(CURRPOS),A
	RET
//---------------- variables
CURRPOS	 DB	PATTSIZE
PLAYER_END
//----------------- TABLES
		ORG	ORG_TBL
BEGIN_TBL	INCBIN	"TABLES.BIN"
END_TBL
		ORG	ORG_TRACK
BEGIN_TRACK	INCBIN	"TRACK.BIN"
END_TRACK
		ORG	ORG_PATT
BEGIN_PATT	INCBIN	"PATTERNS.BIN"
END_PATT
END_MODULE
//----------------- save to TRD
	EMPTYTRD "ay_zip_play.trd"

	SAVETRD "ay_zip_play.trd","MODULE.C",PLAYER,END_MODULE-PLAYER
//----------------- Пример работы плейера
		ORG	#8000
		CALL	PLAYER
LOOP		EI
		HALT
		CALL	PLAYER+3
		JP	LOOP
END_PR
	SAVETRD "ay_zip_play.trd","CODE.C",#8000,END_PR-#8000
		ORG	#9000
BEGIN_BAS
	INCBIN	"loader_m.bas"
END_BAS
	SAVETRD "ay_zip_play.trd","PLAYER.B",BEGIN_BAS,END_BAS-BEGIN_BAS
