User Tools

Site Tools


sqplayerplus

SQ-Tracker player, enhanced


		device zxspectrum128
 
 
		org	$8000
 
DEMOPLAY	di
		ld	sp,DEMOPLAY
		call	SQ_INIT
.loop		ei
		halt
		ld	a,1
		out	(254),a
		call	SQ_PLAY
		xor	a
		out	(254),a
		jr	.loop
 
 
; Povodny player generovany SQ-Linkerom doplneny o GLOBVOL,
; tj. moznost globalneho utlmenia ~ © 2009 mborik/RM-TEAM.
; Upravene na prehravanie SQT suborov, ktorym je potrebne
; na zaciatku relokovat absolutne adresy, dalej bol doplneny
; stavovy bajt podobny aky ma moj PT3 player, cize je mozne
; song neopakovat, alebo fadeoutovat © 2020 mborik/SinDiKat.
 
; Stavovy bajt prehravaca:
; bit.0 nastav ak nechces ziaden looping
; bit.1 nastav ak chces, aby nastal postupny fadeout po par sekundach
; bit.7 sa nastavi vzdy, po odohrati vsetkych pozicii alebo po fadeoute
; ...v jednoduchosti:	2 - fadeout after loop
;			1 - no loop
;			0 - loop forever
SQ_STATUS:	db	2
 
SQ_INIT:	ld	de,(RELOC_BASE)		; nacitame prvy offset, z ktoreho
		ld	hl,BUFFER+10		; po odpocitani skutocnej adresy dat
		xor	a			; bez 10 bajtov ziskavame offset,
		sbc	hl,de			; ktorym musime relokovat vsetky
		push	hl			; absolutne ukazovatele v datach muziky
		ld	de,(RELOC_ENDPTR)
		add	hl,de
		pop	bc
RELOCATOR:	dec	hl
		ld	d,(hl)
		dec	hl
		ld	e,(hl)
		ex	de,hl
		add	hl,bc
		ex	de,hl
		ld	(hl),e
		inc	hl
		ld	(hl),d
		dec	hl
		ld	a,l
		sub	RELOC_BASE % 256
		jr	nz,RELOCATOR
		dec	a
		ld	(SQ_REST+1),a		; resetujem detektor konca skladby
 
		ld	a,8			; inicializacia prehravaca
		ld	(CHNZ1),a
		ld	(CHNZ2),a
		ld	(CHNZ3),a
		ld	bc,$0101
		call	SQ_REND1
CHN_INIT: 	ld	hl,(I_POSITIONS)
		ld	ix,CHNZ1
		call	SQ_I9
		call	SQ_I
		call	SQ_I
SQ_STOP:	ld	de,#073F		; AY registre 7-12 nastav na uplne ticho
CHN_INILOOP:	call	OUT1
		ld	e,0
		inc	d
		ld	a,d
		cp	12
		jr	nz,CHN_INILOOP
		ret
 
SQ_DEADEND:	inc	(hl)			; prehravanie skoncilo, SQ_PLAY je mrtve
		jr	SQ_STOP
 
SQ_PLAY:	ld	hl,SQ_SYS
		dec	(hl)
		jr	nz,CHKFADEOUT
SQ_PLAYSPEED:	ld	(hl),0
		inc	hl
		dec	(hl)
		ld	a,(hl)
		or	a
		call	z,SQ_REST
		cp	4
		call	c,SQ_I
 
SQ_PP		ld	ix,CHNZ1
		ld	c,36
		call	SQ_P
		ld	ix,CHNZ2
		ld	c,18
		call	SQ_P
		ld	ix,CHNZ3
		ld	c,9
		call	SQ_P
 
CHKFADEOUT:	ld	a,0			; kontrola, ci fadeoutujeme
		or	a
		jr	z,SQ_C
		ld	a,(SQ_STATUS)
		bit	7,a
		jr	nz,SQ_DEADEND
 
COUNTFADEOUT:	ld	a,0
		dec	a
		ld	(COUNTFADEOUT+1),a
		jr	nz,GLOBVOL
		ld	a,(GLOBVOL+1)
		inc	a
		cp	16
		jr	z,RESETFADEOUT
		ld	(GLOBVOL+1),a
DIVFADEOUT:	ld	a,0
		srl	a
		ld	l,a
		srl	l
		add	a,l
		jr	nz,DIVFADEOUT1
		inc	a
DIVFADEOUT1:	ld	(COUNTFADEOUT+1),a
		ld	(DIVFADEOUT+1),a
 
GLOBVOL:	ld	a,0			; global attenuation
		ld	(CHNZ1+11),a		; pre vsetky kanaly
		ld	(CHNZ2+11),a
		ld	(CHNZ3+11),a
		bit	3,a			; dosiahla hodnota attenuation
		jr	z,SQ_C			; cislo vacsie ako 8?
		ld	hl,CHNZ1		; tak je nutne upravit sq-flagy,
		ld	de,CHZL 		; aby sa prestali prehravat hw obalky
		ld	c,3			; vo vsetkych troch kanaloch
GLOBVOL1:	res	0,(hl)			; vynulovanim nulteho bytu
		add	hl,de
		dec	c
		jr	nz,GLOBVOL1
 
SQ_C:		xor	a			; vynuluje mixer register
		ld	l,a
		ld	h,a
		ld	(SQ_N+1),hl
		ld	ix,CHNZ1		; postupne prechadza kanalmi
		call	SQ_R
		call	SQ_R
		call	SQ_R
 
SQ_N:		ld	bc,0			; nastavenie mixer registra
		ld	a,b			; B = sumove generatory pre ABC
		rla				; C = tonove generatory pre ABC
		rla
		rla
		or	c
		cpl				; potom sa bity komplementuju
SQ_OFF: 	or	0
		ld	e,a
		ld	d,7			; a posielaju na register 7 AY
OUT1:		ld	bc,$FFFD
		out	(c),d
		ld	b,$BF
		out	(c),e
		ret
 
RESETFADEOUT:	ld	hl,-1
		ld	(SQ_SYS),hl
		ld	hl,SQ_STATUS
		set	7,(hl)
		xor	a
		db	1 ; ld bc,NN namiesto ld a,N
 
ENABLEFADE:	ld	a,48
FORCEFADE:	ld	hl,CHKFADEOUT+1
		inc	(hl)
		ld	(COUNTFADEOUT+1),a
		ld	(DIVFADEOUT+1),a
		cpl
		ld	(SQ_REST+1),a
		ret
 
SQ_I:		ld	hl,0
SQ_I1:		ld	ix,CHNZ1
SQ_I9:		ld	a,(hl)
		or	a
		jr	nz,SQ_I3
		ld	(SQ_REST+1),a		; oznac, ze pri najblizsom patterne
		ld	hl,(I_REPEAT)		; budeme testovat fadeout alebo noloop
SQ_I3:		ld	b,(hl)
		rl	b
		res	5,(ix+0)
		jr	nc,SQ_I4
		set	5,(ix+0)
SQ_I4:		inc	hl
		ld	a,(hl)
		and	15
		ld	(ix+26),a
		ld	a,(hl)
		and	240
		rra
		rra
		rra
		rra
		cp	9
		jr	c,ZBR
		sub	9
		cpl
ZBR:		ld	(ix+24),a
		inc	hl
		ld	(SQ_I+1),hl
		ld	l,b
		ld	h,0
		ld	de,(I_PATTERNS)
		add	hl,de
		ld	e,(hl)
		inc	hl
		ld	d,(hl)
		inc	de
		ld	(ix+22),e
		ld	(ix+23),d
		ld	de,CHZL
		add	ix,de
		ld	(SQ_I1+2),ix
		ret
 
SQ_NOFADE:	call	RESETFADEOUT
		pop	af
		ret
 
SQ_REST:	ld	a,-1
		or	a
		jr	nz,SQ_REST0
		ld	a,(SQ_STATUS)
		rrca			; bit 0. nastaveny = koniec
		jr	c,SQ_NOFADE
		rrca			; bit 1. nastaveny = fadeout
		jr	nc,SQ_REST0
		call	ENABLEFADE
SQ_REST0:	ld	a,(CHNZ1+26)
		ld	(CHNZ1+11),a
		ld	a,(CHNZ2+26)
		ld	(CHNZ2+11),a
		ld	a,(CHNZ3+26)
		ld	(CHNZ3+11),a
		ld	hl,(CHNZ1+22)
		dec	hl
		ld	b,(hl)
		inc	hl
		ld	(CHNZ1+18),hl
		ld	hl,(CHNZ2+22)
		ld	(CHNZ2+18),hl
		ld	hl,(CHNZ3+22)
		ld	(CHNZ3+18),hl
		ld	hl,(CHNZ1+24)
		ld	(CHNZ1+20),hl
		ld	hl,(CHNZ2+24)
		ld	(CHNZ2+20),hl
		ld	hl,(CHNZ3+24)
		ld	(CHNZ3+20),hl
		ld	hl,(SQ_I+1)
		ld	c,(hl)
		inc	hl
		ld	(SQ_I+1),hl
		ld	hl,CHNZ1
		ld	(SQ_I1+2),hl
		ld	a,3
		ld	d,0
SQ_REST1:	res	4,(hl)
		bit	5,(hl)
		jr	z,SQ_REST2
		set	4,(hl)
SQ_REST2:	ld	e,21
		add	hl,de
		ld	(hl),d
		ld	e,CHZL-21
		add	hl,de
		dec	a
		jr	nz,SQ_REST1
SQ_REND1:	ld	(SQ_SYS),bc
		ld	a,c
SQ_REND2:	ld	(SQ_PLAYSPEED+1),a
		ld	a,b
		ret
 
SQ_P:		ld	a,(ix+21)
		or	a
		jr	z,Y01
		dec	(ix+21)
		bit	7,(ix+0)
		jr	nz,Y33
		ret
 
Y01:		ld	e,(ix+18)
		ld	d,(ix+19)
		set	6,(ix+0)
		res	7,(ix+0)
		ld	a,(de)
		inc	de
		bit	7,a
		jr	z,Y02
 
Y05:		ld	(ix+18),e
		ld	(ix+19),d
		ld	b,a
		bit	6,a
		jr	z,Y60
 
		dec	de
		ld	(ix+27),e
		ld	(ix+28),d
Y34:		and	31
		jp	SQ_SMP
 
Y60:		bit	5,a
		jr	nz,Y06
 
		and	15
		bit	4,b
		jr	z,Y07
		neg
Y07:		add	a,(ix+12)
		ld	(ix+12),a
Y33:		ld	e,(ix+27)
		ld	d,(ix+28)
		res	6,(ix+0)
		ld	a,(de)
		bit	7,a
		jr	nz,Y34
		inc	de
		jp	SMP_ORN
 
Y06:		and	15
		ld	(ix+21),a
		bit	4,b
		ret	z
		or	a
		jr	z,Y33
		set	7,(ix+0)
		jr	Y33
 
Y02:		cp	96
		jp	c,Y03
		sub	96
		cp	15
		jr	c,Y04
 
		ld	hl,SQ_OFF+1
		ld	b,a
		ld	a,(hl)
		or	c
		ld	(hl),a
		set	3,(ix+0)
		ld	a,b
		sub	15
		jp	z,Z26
 
Y04:		dec	a
		ex	de,hl
		ld	c,(hl)
		inc	hl
		bit	6,(ix+0)
		jr	z,Y69
		ld	(ix+18),l
		ld	(ix+19),h
		res	6,(ix+0)
Y69:		cp	8
		jr	c,Z38
		set	0,(ix+0)
		ld	l,c
		ld	e,a
		ld	d,13
		call	OUT1
		ld	d,11
		ld	e,l
		jp	OUT1
 
Z38:		cp	6			; channel volume set
		jr	nc,Z36
		bit	4,(ix+0)
		ret	z
		or	a
		jr	nz,Z31
		ld	a,c
SQ_V:		and	15
		ld	(ix+11),a
		ret
 
Z31:		dec	a			; channel volume slide
		jr	nz,Z32
		ld	a,c
		add	a,(ix+11)
		jr	SQ_V
 
Z32:		dec	a			; global volume set
		jr	nz,Z33
		ld	a,c
		ld	(CHNZ1+11),a
		ld	(CHNZ2+11),a
		ld	(CHNZ3+11),a
		ret
 
Z33:		dec	a			; global volume slide
		jr	nz,Z34
		ld	b,3
		ld	de,CHZL
		ld	hl,CHNZ1+11
Z33_2:		ld	a,(hl)
		add	a,c
		and	15
		ld	(hl),a
		add	hl,de
		djnz	Z33_2
		ret
 
Z34:		ld	hl,SQ_SYS		; speed set
		dec	a
		jr	nz,Z35
		ld	a,c
SQ_S:		and	31
		jr	nz,SQ_Z
		ld	a,32
SQ_Z:		ld	(hl),a
		jp	SQ_REND2
 
Z35:		ld	a,(hl)			; speed slide
		add	a,c
		jr	SQ_S
 
Z36:		sub	6
		ld	b,0
		ld	a,c
		ld	c,b
		jr	nz,Z37
		dec	b
		neg
Z37:		set	2,(ix+0)
		ld	(ix+13),c
		ld	(ix+14),c
		ld	(ix+15),a
		ld	(ix+16),b
		ret
 
Y03:		ld	(ix+12),a
		dec	de
		ld	(ix+27),e
		ld	(ix+28),d
		inc	de
		call	SMP_ORN
		bit	6,(ix+0)
		ret	z
Z26:		ld	(ix+18),e
		ld	(ix+19),d
		ret
 
SMP_ORN:	ld	a,(de)
		inc	de
		bit	7,a
		jr	z,SMP_ORN9
		ld	b,a
		rra
		and	31
		call	nz,SQ_SMP
		bit	6,b
		ret	z
		ld	a,(de)
		and	240
		rr	b
		rra
		rra
		rra
		srl	a
		call	nz,SQ_ORN
		ld	a,(de)
		inc	de
		and	15
		ret	z
SMP_ORN9:	jp	Y04
 
SQ_SMP: 	push	bc
		add	a,a
		ld	c,a
		ld	b,0
		ld	a,(ix+0)
		and	%11110000
		ld	(ix+0),a
		ld	hl,(I_SAMPLES)
		add	hl,bc
		ld	c,(hl)
		inc	hl
		ld	b,(hl)
		push	ix
		pop	hl
		inc	hl
		ld	(hl),c
		inc	hl
		ld	(hl),b
		inc	bc
		inc	bc
		inc	hl
		ld	(hl),c
		inc	hl
		ld	(hl),b
		inc	hl
		ld	(hl),32
		inc	hl
		ld	(SQ_NXT+1),hl
		pop	bc
		ld	hl,SQ_OFF+1
		ld	a,(hl)
		or	c
		xor	c
		ld	(hl),a
		ret
 
SQ_ORN: 	add	a,a
		ld	c,a
		ld	b,0
		ld	hl,(I_ORNAMENTS)
		add	hl,bc
		ld	c,(hl)
		inc	hl
		ld	b,(hl)
SQ_NXT: 	ld	hl,0
		ld	(hl),c
		inc	hl
		ld	(hl),b
		inc	hl
		inc	bc
		inc	bc
		ld	(hl),c
		inc	hl
		ld	(hl),b
		inc	hl
		ld	(hl),32
		set	1,(ix+0)
		ret
 
OUT2:		ld	hl,SQ_N+1		; podla carry nastavi v SQ_N
		rl	(hl)			; tonovy generator, sumovy off
		inc	hl			; potom vytiahne cislo kanalu
		rl	(hl)
		ld	a,(ix+17)
		add	a,8			; pripocita k nemu 8
		out	(c),a			; tj. volume registre AY
		ld	b,$BF
		out	(c),e			; a posle hodnotu v E
		jp	SQ_ZCH
 
SQ_R:		ld	l,(ix+3)
		ld	h,(ix+4)
		ld	bc,$FFFD
		ld	d,(ix+0)
		ld	e,0
		bit	3,d			; ak sa nema nic hrat, umlcat
		jr	nz,OUT2
		ld	a,(hl)
		and	15
		jp	nz,SQ_R1
		bit	0,d			; ak sa ma hrat obalka, nastav
		jr	z,SQ_R2
		ld	e,16
		jp	SQ_R2
 
SQ_R1:		sub	(ix+11) 		; od hlasitosti z sa odpocita
		jr	c,SQ_R2 		; global volume nastavenie
		ld	e,a
 
SQ_R2:		ld	a,(ix+17)		; vytiahne sa cislo kanalu
		add	a,8			; pripocita sa 8 cim sa dostnem
		out	(c),a			; na registre hlasitosi AY
		ld	b,$BF
		out	(c),e
		ld	a,(hl)
		inc	hl
		and	240			; vytiahujem sumove data
		rra
		rra
		rra
		ld	d,6
		ld	e,(hl)
		rl	e
		bit	5,(hl)			; zistujem, ci budeme sumiet
		jr	z,SQ_ZNN
		adc	a,0
		ld	b,$FF
		out	(c),d
		ld	b,$BF
		out	(c),a
SQ_ZNN:		ld	a,e
		rla
		ex	de,hl
		ld	hl,SQ_N+1		; nastavime v SQ_N stavy oboch
		rl	(hl)			; generatorov (sum/ton) pre ch.
		inc	hl
		rla
		rl	(hl)
		ex	de,hl
		ld	a,(hl)			; vypocitavanie frekvencie...
		and	31
		ld	d,a
		inc	hl
		ld	e,(hl)
		inc	hl
		push	de
		ld	d,0
		dec	(ix+5)
		jp	nz,FQ_2
		ld	l,(ix+1)
		ld	h,(ix+2)
		ld	a,(hl)
		inc	hl
		cp	32
		ld	c,(hl)
		inc	hl
		jr	nz,FQ_1
		set	3,(ix+0)
		res	1,(ix+0)
FQ_1:		ld	b,a
		add	a,a
		add	a,b
		ld	e,a
		add	hl,de
		ld	(ix+5),c
FQ_2:		ld	(ix+3),l
		ld	(ix+4),h
		ld	a,(ix+12)
		bit	1,(ix+0)
		jr	z,FQ_5
		ld	l,(ix+8)
		ld	h,(ix+9)
		add	a,(hl)
		inc	hl
		dec	(ix+10)
		jp	nz,FQ_4
		ex	af,af'
		ld	l,(ix+6)
		ld	h,(ix+7)
		ld	a,(hl)
		inc	hl
		cp	32
		ld	e,b
		jr	z,FQ_3
		ld	c,(hl)
		ld	e,a
FQ_3:		inc	hl
		add	hl,de
		ld	(ix+10),c
		ex	af,af'
FQ_4:		ld	(ix+8),l
		ld	(ix+9),h
FQ_5:		add	a,(ix+20)
		cp	45
		jr	nc,FQ_6
		add	a,a
		ld	e,a
		ld	hl,FRQ2
		add	hl,de
		ld	d,(hl)
		inc	hl
		jp	FQ_7
 
FQ_6:		ld	hl,FRQ1-45
		ld	e,a
		add	hl,de
FQ_7:		ld	e,(hl)
		ex	de,hl
		pop	de			; ...frekvenciu mame,
		bit	4,d			; bude este fine-tuning?
		res	4,d
		jr	z,FQ_9
		add	hl,de
		db	1 ; ld bc,NN namiesto sbc hl,de
FQ_9:		sbc	hl,de
		bit	2,(ix+0)
		jr	z,OUT9
		ld	c,(ix+13)
		ld	b,(ix+14)
		add	hl,bc
		ex	de,hl
		ld	l,(ix+15)
		ld	h,(ix+16)
		add	hl,bc
		ld	(ix+13),l
		ld	(ix+14),h
		ex	de,hl
 
OUT9:		ld	a,(ix+17)		; vytiahi cislo kanalu
		add	a,a			; vynasob dvoma
		ld	bc,$FFFD		; a naprogramuj freq tonu
		out	(c),a
		ld	b,$BF
		out	(c),l
		inc	a
		ld	b,$FF
		out	(c),a
		ld	b,$BF
		out	(c),h
SQ_ZCH: 	ld	de,CHZL 		; prejdi s IX na dalsi kanal
		add	ix,de
		ret
 
FRQ2:		db	13,93,12,156
		db	11,231,11,60
		db	10,155,10,2,9,115
		db	8,235,8,107,7,242
		db	7,128,7,20,6,174
		db	6,78,5,244,5,158
		db	5,79,5,1,4,185
		db	4,117,4,53,3,249
		db	3,192,3,138,3,87
		db	3,39,2,250,2,207
		db	2,167,2,129,2,93
		db	2,59,2,27,1,252
		db	1,224,1,197,1,172
		db	1,148,1,125,1,104
		db	1,83,1,64
		db	1,46,1,29,1,13
 
FRQ1:		db	254,240,226,214
		db	202,190,180,170
		db	160,151,143,135
		db	127,120,113,107
		db	101,95,90,85,80
		db	76,71,67,64,60,57
		db	53,50,48,45,42,40
		db	38,36,34,32,30,28
		db	27,25,24,22,21,20
		db	19,18,17,16,15,14
 
CHNZ1:		db	0
		dw	0,0,0,0,0,0,0,0
		dw	2,0,0,0,0,0
CHNZ2:		db	0
		dw	0,0,0,0,0,0,0,0
		dw	1,0,0,0,0,0
CHNZ3:		db	0
		dw	0,0,0,0,0,0,0,0
		dw	0,0,0,0,0,0
 
SQ_SYS: 	dw	#0101
 
CHZL:		equ	CHNZ2-CHNZ1	; offset medzi kanalmi
 
 
;		org	KAMKOLVEK
 
BUFFER:		ds	2		; dlzka songu
RELOC_BASE:
I_SAMPLES:	ds	2		; adresa lookup tabulky samplov
I_ORNAMENTS:	ds	2		; adresa lookup tabulky ornamentov
I_PATTERNS:	ds	2		; adresa lookup tabulky patternov
I_POSITIONS:	ds	2		; adresa definicii pozicii
I_REPEAT:	ds	2		; ukazovatel na repeat poziciu
RELOC_ENDPTR:	ds	2		; tu je uz ukazovat na prvy sampel
 
; data songu formatu .sqt zacinaju na navesti BUFFER
; ich zaciatok su absolutne adresy, ktore treba najprv relokovat v SQ_INIT
		org	BUFFER
 
		incbin music.sqt
 
 
		savesna "sqplayer.sna",DEMOPLAY
		savetap "sqplayer.tap",CODE,"music",DEMOPLAY,$-DEMOPLAY,DEMOPLAY

Navigation: general . math . graphic . sound . system . other . back to start

sqplayerplus.txt · Last modified: 2020/04/09 22:42 by darkbyte