;******************************
;*
;* effect.... 
;*
;* r0 = current channel struct
;* r6 = mode struct
;*

effectTonePlusVolSlide	;5

	push	r7
	
	;
	
	gpci	r7,2
	br	TonePortNoChange
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	gpci	r7,2
	br	effectVolumeSlide
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;

	rqpop
	nop
	nop
	pop	r7
	nop
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot


;******************************
;*
;* checkTonePorta
;*
;* r0 = current channel struct
;* r6 = mode struct
;*

effectTonePortamento		;3

	push	r1
	push	r2
	push	r5
	push	r7
	
	;
	
	rqldi	r0,channelStCmd 		;get effect (cmd)
	rqldi	r0,channelStToneportspeed 	
	movei	r5,$f
	ld	r1	;cmd
	ld	r2	;tone porta speed
	
	moveih	r1,0	;00XY
	nop
	cmpeqi	r1,0		;		 XY == 0?
	movets	r2,r2,r1	;toneportspeed =	  toneportspeed : XY	
	
	ssto	channelStToneportspeed
	stwo	r0,r2		;store toneportspeed
	
	; pt_TonePortNoChange(currentChannel);
	
        gpci	r7,2
	br	TonePortNoChange	
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;

	rqpop
	rqpop
	rqpop
	pop	r7	
	pop	r5
	pop	r2

	rqpop
	jmpi	r7,0
	nop		;delay slot
	pop	r1	;delay slot
	nop		;delay slot
	nop		;delay slot
	
;***	
	
TonePortNoChange	
	
	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r5
	push	r6
	push	r7
	
	;r1,r2,r3,r4,r5 save
	
	rqldi	r0,channelStWantPeriode
	rqldi	r0,channelStToneportdirec
	rqldi	r0,channelStToneportspeed
	ld	r1	;want periode
	ld	r2	;direction
	ld	r3	;speed
	
	cmpeqi	r1,0	;wantPeriode
	brts	TonePortNoChangeNoWantPeriode
	rqldi	r0,channelStPeriode	;		delay slot
	nop				;		delay slot
	nop				;		delay slot
	ld	r4			;periode	delay slot
	
	
	cmpeqi	r2,0	;direction == 0 -> down
	brtc	TonePortUp
	movei	r5,0	;r5 = 0		delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	; down

	add	r4,r4,r3	;periode += speed		
	br	TonePortFinish		
	nop														;delay slot
	cmple	r4,r1		;	    	   periode <= want periode?						;delay slot
	movets	r4,r4,r1	;periode 	=			     periode 		: want periode		;delay slot
	movets	r1,r1,r5	;want periode   =			     want periode 	: 0			;delay slot
	
TonePortUp	

	; up
	
	sub	r4,r4,r3	;periode -= speed
	nop
	cmplo	r4,r1		;	    	   periode < want periode?
	movets	r4,r1,r4	;periode 	=			     want periode	: periode
	movets	r1,r5,r1	;want periode   =			     0			: want periode 	
	
	;
	
TonePortFinish	
	
	ssto	channelStPeriode		;store periode
	stwo	r0,r4
	ssto	channelStWantPeriode		;store want periode
	stwo	r0,r1
	
	              
	
TonePortNoChangeNoWantPeriode
	
	;; currentChannel.setHWPeriode(currentChannel.n_periode);
	
	dexti	>channelSetPeriode
	movei	r2,channelSetPeriode
	gpci	r7,2
	jmpi	r2,0		;set new periode
	or	r6,r0,r0	;channel struct
	or	r0,r4,r4	;periode to set
	nop			;delay slot
	nop			;delay slot
	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r5
	pop	r4	
	pop	r3	
	pop	r2	
	
	rqpop	
	rqpop
	jmpi	r7,0
	pop	r1	;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* checkTonePorta
;*
;* r0 = current channel struct
;* r6 = mode struct
;*

checkTonePorta		;3 & 5 indirect call from tick channel loop

	;r6 = mode struct
	;r0 = current channel adr
	;r2 = sample number
        ;r3 = note
	;r4 = cmd   
	
	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r6
	push	r7
	
	; currentChannel.n_periode = searchPeriode(currentChannel.n_note, currentChannel.n_fineTune);
	
	push	r0	;store channel struct
	nop
	rqldi	r0,channelStNote
	rqldi	r0,channelStFineTune
	nop
	ld	r0
	ld	r1
 
	gpci	r7,2
	br	periodeSearch
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot		;return: 	r0 = periode
	nop		;delay slot		;		r1 = fine tune (0..7 -8..-1)
	
	rqpop
	or	r1,r0,r0	;r1 = periodeToSlide
	nop
	pop	r0	;restore channel struct
	
	ssto	channelStWantPeriode
	stwo	r0,r1		; currentChannel.n_wantPeriode = periodeToSlide; // periode want (slide to)
	
	rqldi	r0,channelStPeriode
	nop
	nop
	ld	r2	;periode
	
	movei	r3,0	;direction = 0 default
	cmple	r1,r2	;periodeToSlide <= currentChannel.n_periode
	addtqi	r3,r3,0	;					    == true  direction ++
	
	ssto	channelStToneportdirec
	stwo	r0,r3	;store direction
		    
	;pt_CheckMoreEffects(currentChannel);

	gpci	r7,2
	br	modCheckMoreEffects    
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r4
	pop	r3	
	pop	r2	
	pop	r1	
	
	rqpop	
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot
	
	
	
;******************************
;*
;* effectVibratoPlusVolSlide
;*
;* r0 = current channel struct
;* r6 = mode struct
;*		
	
effectVibratoPlusVolSlide	;6
	
	push	r7
	
	gpci	r7,2
	br	effectVibrato2
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	gpci	r7,2
	br	effectVolumeSlide
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	rqpop
	nop
	nop
	pop	r7
	nop
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* EEffectPortaUp
;*
;* r0 = current channel struct
;* r6 = mode struct
;*			
	
effectVibrato	

	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r6
	push	r7	
	
	;

	rqldi	r0,channelStCmd 	;get effect (cmd)
	rqldi	r0,channelStVibratoCmd	;vibrato comd
	movei	r5,$f
	ld	r1	;cmd
	ld	r4	;vibrato cmd
	
	moveih	r1,0	;00XY
	nop
	bic	r2,r1,r5	;r2 = 00X0
	and	r3,r1,r5	;r3 = 000Y
	
	
	cmpeqi	r1,0	;xy == 0
	brts	noVibratoXYUpdate
	nop		;delay slot
	nop		;delay slot	
	nop		;delay slot
	nop		;delay slot	
	
	
	cmpeqi	r3,0	;		y == 0
	tnt		;		y != 0
	bicts	r4,r5			; vcmd &= $fff0 
	nop
	orts	r4,r3			; vcmd |= Y
	
	cmpeqi	r2,0	;		x == 0
	tnt		;		x != 0
	andts	r4,r5			; vcmd &= $f
	nop
	orts	r4,r2			; vcmd |= Y0
	    
	ssto	channelStVibratoCmd
	stwo	r0,r4			;store vcmd

noVibratoXYUpdate 
	    
	gpci	r7,2
	br	effectVibrato2
        nop		;delay slot
	nop		;delay slot	
	nop		;delay slot
	nop		;delay slot 
	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r4
	pop	r3	
	pop	r2	
	pop	r1	
	
	rqpop	
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot	

;******************************
;*
;* effectVibrato2	real vibrato	
;*
;* r0 = current channel struct
;* r6 = mode struct
;*		

effectVibrato2

	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r6
	push	r7	

	; uint tablePos = currentChannel.n_vibratopos & 0x1f;          
        ; bool neg = (currentChannel.n_vibratopos & 0x20) != 0;
	
	rqldi	r0,channelStVibratoPos
	rqldi	r0,channelStVibratoCmd
	rqldi	r0,channelStPeriode
	ld	r1		;table pos
	ld	r4		;vibrato comd
	ld	r5		;current periode
	movei	r2,$1f
	movei	r3,0
	extri	r1,5		;
	addtqi	r3,r3,0		;r3 = neg = 1 if negative
	and	r1,r1,r2	;r1 = tablePos = 0..1f 
	
	;dump
	
	;no wave ctrl implemented
	
	; tableValue = vibratoTable[tablePos];    // sinus
	
	dexti	>vibratoTable
	movei	r2,vibratoTable
	nop
	rqld	r2,r1		;vibratoTable[tablePos]
	nop
	movei	r1,0
	ld	r2		;tableValue 
	

        ; tableValue = (neg) ? -tableValue : tableValue; // +-
	
	nop
	sub	r1,r1,r2	;-tableValue = 0 - tableValue
	cmpeqi	r3,1		;neg ?
	movets	r2,r1,r2	;	-tableValue : tableValue	
	
	;
	
	 ; tableValue *= ((int)(currentChannel.n_vibratocmd & 0xf)); // multiply with dept 
	 
	movei	r3,$f
	nop	
	and	r3,r4,r3	;vibrato cmd & 0xf
	nop
	muls	r2,r2,r3	;table value * (vibrato cmd & 0xf)
	nop
	asri	r2,7		; tableValue >>= 7;   // divide 128
	nop 
        add	r5,r5,r2	;int periode = currentChannel.n_periode + tableValue; // calc last set periode + vibrato value       
	    
	; currentChannel.n_vibratopos += (currentChannel.n_vibratocmd >> 4); // add speed tp vibrato pos

	rqldi	r0,channelStVibratoPos
	nop
	nop
	ld	r2	;vibrato pos
	lsrqi	r3,r4,4	;vibrato cmd>>4
	nop
	add	r2,r2,r3	;vibrato pos + (vibrato cmd>>4)
	
	ssto	channelStVibratoPos
	stwo	r0,r2		;store vibrato pos
	
        ; currentChannel.setHWPeriode(periode); // store to hw   

	;r0 = channel struct
	;r1 = new periode -> store to hardware
	;r6 = mod struct

	dexti	>channelSetPeriode
	movei	r2,channelSetPeriode
	gpci	r7,2
	jmpi	r2,0		;set new periode
	or	r6,r0,r0	;channel struct
	or	r0,r5,r5	;periode to set
	nop			;delay slot
	nop			;delay slot
	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r4
	pop	r3	
	pop	r2	
	pop	r1	
	
	rqpop	
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot	
	
vibratoTable 
	
	.data	0, 24, 49, 74, 97,120,141,161
	.data	180,197,212,224,235,244,250,253
	.data	255,253,250,244,235,224,212,197
	.data	180,161,141,120, 97, 74, 49, 24		

;******************************
;*
;* effectTremolo
;*
;* r0 = current channel struct
;* r6 = mode struct
;*
	
effectTremolo			;7
	
	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r6
	push	r7	
	
	;

	rqldi	r0,channelStCmd 	;get effect (cmd)
	rqldi	r0,channelStTremoloCmd	;tremolo cmd
	movei	r5,$f
	ld	r1	;cmd
	ld	r4	;tremolo cmd
	
	moveih	r1,0	;00XY
	nop
	bic	r2,r1,r5	;r2 = 00X0
	and	r3,r1,r5	;r3 = 000Y
	
	
	cmpeqi	r1,0	;xy == 0
	brts	noTremoloXYUpdate
	nop		;delay slot
	nop		;delay slot	
	nop		;delay slot
	nop		;delay slot	
	
	
	cmpeqi	r3,0	;		y == 0
	tnt		;		y != 0
	bicts	r4,r5			; tcmd &= $fff0 
	nop
	orts	r4,r3			; tcmd |= Y
	
	cmpeqi	r2,0	;		x == 0
	tnt		;		x != 0
	andts	r4,r5			; tcmd &= $f
	nop
	orts	r4,r2			; tcmd |= Y0
	    
	ssto	channelStTremoloCmd
	stwo	r0,r4			;store tcmd

noTremoloXYUpdate 
	    
	gpci	r7,2
	br	effectTremolo2
        nop		;delay slot
	nop		;delay slot	
	nop		;delay slot
	nop		;delay slot 
	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r4
	pop	r3	
	pop	r2	
	pop	r1	
	
	rqpop	
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot

;******************************
;*
;* effectTremolo2	real tremolo	
;*
;* r0 = current channel struct
;* r6 = mode struct
;*		

effectTremolo2

	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r6
	push	r7	

	; uint tablePos = currentChannel.n_tremolopos & 0x1f;          
        ; bool neg = (currentChannel.n_tremolopos & 0x20) != 0;
	
	rqldi	r0,channelStTremoloPos
	rqldi	r0,channelStTremoloCmd
	rqldi	r0,channelStVolume
	ld	r1		;table pos
	ld	r4		;vibrato comd
	ld	r5		;current volume
	movei	r2,$1f
	movei	r3,0
	extri	r1,5		;
	addtqi	r3,r3,0		;r3 = neg = 1 if negative
	and	r1,r1,r2	;r1 = tablePos = 0..1f 
	
	;dump
	
	;no wave ctrl implemented
	
	; tableValue = vibratoTable[tablePos];    // sinus
	
	dexti	>vibratoTable
	movei	r2,vibratoTable
	nop
	rqld	r2,r1		;vibratoTable[tablePos]
	nop
	movei	r1,0
	ld	r2		;tableValue 
	

        ; tableValue = (neg) ? -tableValue : tableValue; // +-
	
	nop
	sub	r1,r1,r2	;-tableValue = 0 - tableValue
	cmpeqi	r3,1		;neg ?
	movets	r2,r1,r2	;	-tableValue : tableValue	
	
	;
	
	 ; tableValue *= ((int)(currentChannel.n_vibratocmd & 0xf)); // multiply with dept 
	 
	movei	r3,$f
	nop	
	and	r3,r4,r3	;vibrato cmd & 0xf
	nop
	muls	r2,r2,r3	;table value * (vibrato cmd & 0xf)
	nop
	asri	r2,6		; tableValue >>= 6;   // divide 64
	nop 
        add	r5,r5,r2	;int volume = currentChannel.n_volume + tableValue; // calc last set periode + vibrato value       
	    
	; currentChannel.n_tremolopos += (currentChannel.n_tremolocmd >> 4); // add speed tp vibrato pos

	rqldi	r0,channelStTremoloPos
	nop
	nop
	ld	r2	;vibrato pos
	lsrqi	r3,r4,4	;vibrato cmd>>4
	nop
	add	r2,r2,r3	;tremolo pos + (tremolo cmd>>4)
	
	ssto	channelStTremoloPos
	stwo	r0,r2		;store tremolo pos
	
        ; currentChannel.setHWPeriode(periode); // store to hw   

	;r0 = channel struct
	;r1 = new periode -> store to hardware
	;r6 = mod struct

	movei	r2,64	;volume clamp
	cmploi	r5,64
	movets	r5,r5,r2		;vol = vol<64?vol:64
	
	dexti	>channelSetVolume
	movei	r2,channelSetVolume
	gpci	r7,2
	jmpi	r2,0		;set new periode
	or	r6,r0,r0	;channel struct
	or	r0,r5,r5	;volume to set
	nop			;delay slot
	nop			;delay slot
	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r4
	pop	r3	
	pop	r2	
	pop	r1	
	
	rqpop	
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot	
	
;******************************
;*
;* EEffectPortaUp
;*
;* r0 = current channel struct
;* r6 = mode struct
;*		
	
effectArpeggio			;0

	push	r0
	push	r1
	push	r2
	push	r3
	push	r4
	push	r6
	push	r7
	
	
	;
	
	rqldi	r0,channelStCmd 	;get effect (cmd)
	rqldi	r6,modTickCounter 	;get tick counter
	rqldi	r0,channelStPeriode 	;current periode
	ld	r1			;cmd 0EXY
	ld	r2			;counter
	ld	r4			;current periode
	or	r3,r2,r2		;r3 = counter backup
	dexti	$55
	muli	r2,$55			;counter * $5555
	rqldi	r0,channelStFineTune 	;get finetune				
	gmulhi	r2			;
	nop
	ld	r5			;finetune	
	muli	r2,3			;*3
	moveih	r1,0			;cmd 00XY
	sub	r2,r3,r2		;counter backup = r3 - counter backup
	nop
	
	;r0 = channel struct
	;r1 = cmd
	;r2 = counter (1,2,3)
	;r3 = free
	;r4 = periode
	;r5 = finetune
	
	dexti	>effectArpeggioFinish
	movei	r7,effectArpeggioFinish		;return address
	
	cmpeqi	r2,1	 ;periode = searchPeriodeWithFineTune(currentChannel.n_periode , currentChannel.n_fineTune,effect_x(currentChannel.n_cmd)); break;
	brts	effectArpeggioCalculatePeriode
	lsrqi	r3,r1,4	;r3 = 000X	delay slot
	nop		;		delay slot
	nop		;		delay slot
	nop		;		delay slot
	nop		;		delay slot
	
	cmpeqi	r2,2	 ;periode = searchPeriodeWithFineTune(currentChannel.n_periode , currentChannel.n_fineTune,effect_y(currentChannel.n_cmd)); break;
	brts	effectArpeggioCalculatePeriode
	movei	r3,$f		;		delay slot
	nop			;		delay slot
	and	r3,r1,r3	;r3 = 000Y	delay slot
	nop			;		delay slot
	nop			;		delay slot
	
	;not 1 and 2 so store periode into r1
		
	or	r1,r4,r4	;	
	
	;

effectArpeggioFinish	

	;r0 = channel struct
	;r1 = new periode -> store to hardware
	;r6 = mod struct
	
	dexti	>channelSetPeriode
	movei	r2,channelSetPeriode
	gpci	r7,2
	jmpi	r2,0		;set new periode
	or	r6,r0,r0	;channel struct
	or	r0,r1,r1	;periode to set
	nop			;delay slot
	nop			;delay slot

	
	;
	
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r4
	pop	r3	
	pop	r2	
	pop	r1	
	
	rqpop	
	jmpi	r7,0
	nop		;delay slot
	pop	r0	;delay slot
	nop		;delay slot
	nop		;delay slot
	
;	
;r3 = offset	
;r4 = periode
;r5 = finetune	
	
effectArpeggioCalculatePeriode

	push	r0
	push	r5
	push	r7
	
	dexti	>periodeSearchWithOffset
	movei	r0,periodeSearchWithOffset
	gpci	r7,2	
	jmpi	r0,0
	or	r0,r4,r4	;delay slot	periode
	or	r1,r5,r5	;delay slot	finetune
	or	r5,r3,r3	;delay slot	offset
	nop		;delay slot	return r1 = new periode
	
	rqpop
	rqpop
	rqpop
	pop	r7
	pop	r5
	pop	r0	

	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	
	
;******************************
;*
;* EEffectPortaUp
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	

effectPortaUp	;1

	push	r0
	push	r1
	push	r2
	push	r3
	push	r6
	push	r7
	
	;
	
	rqldi	r0,channelStCmd 	;get effect (cmd)
	rqldi	r0,channelStPeriode
	movei	r2,$ff
	ld	r1		;effect
	ld	r3		;periode
	and	r1,r1,r2	;XY
	
	;

	movei	r2,$71
	sub	r3,r3,r1	;periode -= XY
	nop
	
	cmplos	r3,r2		;	   (periode < $71)
	movets	r3,r2,r3	;periode =		     ? $71 : periode 
	
	ssto	channelStPeriode
	stwo	r0,r3		;store periode back

	;set hardware periode
	
	dexti	>channelSetPeriode			
	movei	r2,channelSetPeriode
	gpci	r7,2				; r0 = value
	jmpi	r2,0                            ; r6 = channel struct
	or	r6,r0,r0	;channelstruct		delay slot
	or	r0,r3,r3	;value = periode	delay slot	
	nop			;delay slot
	nop			;delay slot
			
	;		
			
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r3
	pop	r2	
	pop	r1	
	pop	r0	
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* EEffectPortaDown
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	
	
	
effectPortaDown		;2

	push	r0
	push	r1
	push	r2
	push	r3
	push	r6
	push	r7
	
	;
	
	rqldi	r0,channelStCmd 	;get effect (cmd)
	rqldi	r0,channelStPeriode
	movei	r2,$ff
	ld	r1		;effect
	ld	r3		;periode
	and	r1,r1,r2	;XY
	
	;

	dexti	$3
	movei	r2,$58
		
	add	r3,r3,r1	;periode += XY
	nop
	
	cmple	r3,r2		;	   (periode <= $358)
	movets	r3,r3,r2	;periode =		     ? periode : $358
	
	ssto	channelStPeriode
	stwo	r0,r3		;store periode back

	;set hardware periode
	
	dexti	>channelSetPeriode			
	movei	r2,channelSetPeriode
	gpci	r7,2				; r0 = value
	jmpi	r2,0                            ; r6 = channel struct
	or	r6,r0,r0	;channelstruct		delay slot
	or	r0,r3,r3	;value = periode	delay slot	
	nop			;delay slot
	nop			;delay slot
			
	;		
			
	rqpop
	rqpop
	rqpop
	poparqp	r7
	poparqp	r6	
	poparqp	r3
	pop	r2	
	pop	r1	
	pop	r0	
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* effectSampleOffset 
;*
;* r0 = current channel struct
;* r6 = mode struct
;*

effectSampleOffset	;*9

	push	r1
	push	r2
	
	rqldi	r0,channelStLength
	rqldi	r0,channelStCmd 	;get effect (cmd)
	nop
	ld	r2	;length
	ld	r1	;effect
	nop
	moveih	r1,0	;00XY
	nop
	swp	r1,r1	;*$100
	nop
	
	cmplo	r1,r2	;offset < length
	brtc	effectSampleOffsetOverflow	;!
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
		
	;dump	
	ssto	channelStStart
	stwo	r0,r1	;start = offset
	
	
effectSampleOffsetOverflow	
	
	rqpop
	rqpop
	jmpi	r7,0
	pop	r2	;delay slot
	pop	r1	;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* effectPositionJump 
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	
	
effectPositionJump	;* b

	push	r1
	push	r2
	
	;

	rqldi	r6,modTickCounter
	rqldi	r0,channelStCmd 	;get effect (cmd)
	nop
	ld	r2	;tick counter
	ld	r1	;effect
	
	cmpeqi	r2,0	
	brtc	effectPositionJumpTickNotZero
	moveih	r1,0	;00XY		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	ssto	modCurrentSongPosition
	stwo	r6,r1			; song position = xy (no test again song length!)
	
	dexti	$ff
	movei	r0,$ff
	ssto	modCurrentRowPosition
	stwo	r6,r0			;row = -1
		
effectPositionJumpTickNotZero	
	
	;
	
	rqpop
	rqpop
	jmpi	r7,0
	pop	r2	;delay slot
	pop	r1	;delay slot
	nop		;delay slot
	nop		;delay slot

;******************************
;*
;* effectVolumeSlide
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	
	
effectVolumeSlide		;a

	push	r1
	push	r2
	push	r3
	
	;
  	    
	rqldi	r0,channelStCmd 	;get effect (cmd)
	rqldi	r0,channelStVolume
	nop
	ld	r1			;cmd
	ld	r3			;volume
	movei	r2,$f
	moveih	r1,0	;00XY
	nop
	and	r2,r1,r2	;r2 = Y
	lsri	r1,4		;r1 = X
	
	sub	r3,r3,r2	;volume - Y
	nop
	add	r3,r3,r1	;volume + X
	
	
	movei	r2,64	;volume clamp
	cmploi	r3,64
	movets	r3,r3,r2		;vol = vol<64?vol:64
	
	ssto	channelStVolume
	stwo	r0,r3			;store volume
	
	;
	
	rqpop
	rqpop
	rqpop
	pop	r3
	pop	r2	
	pop	r1	
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* effectVolumeChange 
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	
	
effectVolumeChange	;* c

	push	r1
	push	r2
	
	;
  	    
	rqldi	r0,channelStCmd 	;get effect (cmd)
	nop
	nop
	ld	r1
	nop
	moveih	r1,0	;00XX
	movei	r2,64	;volume clamp
	
	cmploi	r1,64
	movets	r1,r1,r2		;r1 = vol<64?vol:64
	
	ssto	channelStVolume
	stwo	r0,r1			;store volume
	
	;
	
	rqpop
	rqpop
	jmpi	r7,0
	pop	r2	;delay slot
	pop	r1	;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* effectPatternBreak 
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	
	
effectPatternBreak	;* d

	push	r1
	push	r2
	push	r3
		
	;
	
	rqldi	r6,modTickCounter
	rqldi	r0,channelStCmd 	;get effect (cmd)
	nop
	ld	r2	;tick counter
	ld	r1	;effect
	
	cmpeqi	r2,0	
	brtc	effectPatternBreakTickNotZero
	moveih	r1,0		;00XY		;delay slot
	movei	r3,$f				;delay slot
	lsrqi	r2,r1,4		;r2 = 000X	;delay slot
	and	r1,r1,r3	;r1 = 000Y	;delay slot
	
	muli	r2,10		;r2 * 10 	x*10
	
	rqldi	r6,modCurrentSongPosition 
	add	r2,r2,r1	;r2 += r1	x*10+y
	nop
	ld	r1	;song position
	subi	r2,1		;r2 --		x*10+y-1
	addi	r1,1	;song position ++
		
	ssto	modCurrentSongPosition
	stwo	r6,r1	;store song position
	
	ssto	modCurrentRowPosition
	stwo	r6,r2	;store current row position (x*10+y-1)
			
effectPatternBreakTickNotZero	
	
	;
	
	rqpop
	rqpop
	rqpop
	pop	r3	
	pop	r2	
	pop	r1	
	
	jmpi	r7,0
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
;******************************
;*
;* effectECommands 
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	
	
effectECommands		;* e

	push	r1
	push	r2
	push	r7
	
	;
	
	rqldi	r0,channelStCmd 	;get effect (cmd)
	dexti	>EEffectsList
	movei	r2,EEffectsList
	ld	r1
	nop
	moveih	r1,0	;00XY
	nop
	lsri	r1,4	;r1 = 000X
	
	nop
	add	r2,r2,r1	;effectList + X
	nop
	rqldi	r2,0		;request pointer at position
	nop
	nop
	ld	r2		;pointer at position
	
	gpci	r7,2
	jmpi	r2,0		;jump to e effect
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot

	;back
	
EEffectDefault	
	
	;

	rqpop
	nop
	nop
	pop	r7
	    
	rqpop
	rqpop
	jmpi	r7,0
	pop	r2	;delay slot
	pop	r1	;delay slot
	nop		;delay slot
	nop		;delay slot
	
EEffectsList

		word	EEffectFilterOn			;*0
		word	EEffectFinePortaUp		;*1
		word	EEffectFinePortaDown		;2
		word	EEffectSetGlissControl		;3
		word	EEffectSetVibratoControl	;4
		word	EEffectSetFineTune		;5
		word	EEffectJumpLoop			;6
		word	EEffectSetTremoloControl	;7
		word	EEffectKarplusStrong		;8
		word	EEffectRetrigNote		;9
		word	EEffectVolumeFineUp		;a
		word	EEffectVolumeFineDown		;b
		word	EEffectNoteCut			;c
		word	EEffectNoteDelay		;d
		word	EEffectPatternDelay		;e
		word	EEffectDefault			;f	
	         
;******************************
;*
;* effectSetSpeed 
;*
;* r0 = current channel struct
;* r6 = mode struct
;*	
	
effectSetSpeed		;* f

	push	r1
	push	r2
	push	r7
	
	;
  	    
	rqldi	r0,channelStCmd 	;get effect (cmd)
	nop
	nop
	ld	r1
	nop
	moveih	r1,0		;00XY
	nop
	
	cmpeqi	r1,0			;xy == 0 -> not allowed
	brts	illegalSpeed
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	cmplosi	r1,$20			;xy < $20 -> speed setup
	brts	effectSetRealSpeed
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	nop		;delay slot
	
	;xy >= $20 is bpm setup
	
	gpci	r7,2
	br	modUpdateBPM	;update bpm (set timer ....)
	ssto	modBpm		;delay slot
        stwo	r6,r1		;delay slot	store bpm value
	nop			;delay slot
	nop			;delay slot
	
illegalSpeed	    
	    
	rqpop
	nop
	nop
	pop	r7
	    
	rqpop
	rqpop
	jmpi	r7,0
	pop	r2	;delay slot
	pop	r1	;delay slot
	nop		;delay slot
	nop		;delay slot
	
effectSetRealSpeed

	br	illegalSpeed
	ssto	modSpeed	;delay slot
	stwo	r6,r1		;store new speed	delay slot
	nop			;delay slot
	nop			;delay slot