.def channelRepeatStart 0 .def channelRepeatLength 1 .def channelIncrement 2 .def channelVolume 3 .def channelLength 4 .def channelCurrentPositionLow 5 .def channelCurrentPositionHigh 6 .def channelSampleAdrLow 7 .def channelSampleAdrHigh 8 .def channelDummy 9 ;following values are only for store mod values (dont reservate size if not needed) .def channelStCmd 10 ;0 .def channelStNote 11 ;1 .def channelStPeriode 12 ;2 .def channelStVolume 13 ;3 .def channelStSampleNumber 14 ;4 .def channelStStart 15 ;5 .def channelStRealLength 16 ;6 .def channelStLength 17 ;7 .def channelStFineTune 18 ;8 .def channelStRepeatStart 19 ;10 .def channelStRepeatLength 20 ;11 .def channelStVibratoCmd 21 ;12 .def channelStVibratoPos 22 ;13 .def channelStLoopPos 23 ;14 .def channelStLoopCount 24 ;15 .def channelStTremoloCmd 25 ;16 .def channelStTremoloPos 26 ;17 .def channelStWantPeriode 27 ;18 .def channelStToneportdirec 28 ;19 .def channelStToneportspeed 29 ;20 .def channelStructSize 32 ; channel init !!! ;****************************** ;* ;* channelSetSampleAddress ;* ;* r0 = sample low ;* r1 = sample high ;* r6 = channel struct ;* channelSetSampleAddress jmpi r7,0 ssto channelSampleAdrLow ;delay slot stwo r6,r0 ;delay slot ssto channelSampleAdrHigh ;delay slot stwo r6,r1 ;delay slot ;****************************** ;* ;* channelSetRepeatStart ;* ;* r0 = value ;* r6 = channel struct ;* channelSetRepeatStart jmpi r7,0 ssto channelRepeatStart ;delay slot stwo r6,r0 ;delay slot nop ;delay slot nop ;delay slot ;****************************** ;* ;* channelSetRepeatLength ;* ;* r0 = value ;* r6 = channel struct ;* channelSetRepeatLength push r1 push r2 push r3 movei r1,$ff rqldi r6,channelRepeatStart moveih r1,$ff movei r3,0 ld r2 ;get rep start cmploi r0,3 ;length <3 is no repeat movets r0,r1,r0 ;no repeat -> rep length = $ffff else rep length movets r2,r3,r2 ; rep start = $0 else rep start ssto channelRepeatStart st r6,r2 ;store repeat start rqpop rqpop rqpop pop r3 pop r2 pop r1 jmpi r7,0 ssto channelRepeatLength ;store repeat length delay slot stwo r6,r0 ; delay slot nop ; delay slot nop ; delay slot ;****************************** ;* ;* channelSetVolume ;* ;* r0 = value ;* r6 = channel struct ;* channelSetVolume jmpi r7,0 ssto channelVolume ;delay slot stwo r6,r0 ;delay slot nop ;delay slot nop ;delay slot ;****************************** ;* ;* channelSetSampleLength ;* ;* r0 = value ;* r6 = channel struct ;* channelSetSampleLength jmpi r7,0 ssto channelLength ;delay slot stwo r6,r0 ;delay slot nop ;delay slot nop ;delay slot ;****************************** ;* ;* channelSetSampleStart ;* ;* r0 = value (in bytes) ;* r6 = channel struct ;* channelSetSampleStart ;dump ;add r0,r0,r0 ; *2 ssto channelCurrentPositionHigh stwo r6,r0 jmpi r7,0 movei r0,0 ;delay slot nop ;delay slot ssto channelCurrentPositionLow ;delay slot stwo r6,r0 ;delay slot ;****************************** ;* ;* channelSetPeriode ;* ;* r0 = value ;* r6 = channel struct ;* ;* note: this function is not irq save ;* channelSetPeriode push r2 push r3 ;store irq_enable cmpeqi r0,0 ;periode 0? if true set increment to 0 brts skipDiv0 nop ;delay slot movei r2,$7c ;delay slot movei r3,$37 ;delay slot moveih r2,$6b ;r3:r2 = 3631996 ;delay slot udivinit 21 ;22 bit division (-1) udivsdd r2 udivsddh r3 ; movei r2,4 ;(4+1)*4 = 20 udivsdv r0 ;r3:r2 / periode pToILoop subi r2,1 brts pToILoop udivstep ;delay slot udivstep ;delay slot udivstep ;delay slot udivstep ;delay slot udivstep ;21 udivstep ;22 udivgq r0 ;get result skipDiv0 rqpop rqpop jmpi r7,0 pop r3 ;delay slot pop r2 ;delay slot ssto channelIncrement ;delay slot stwo r6,r0 ;store new increment value delay slot ;****************************** ;* ;* channelBufferdCopy ;* ;* r0 = counter ;* r5 = return address !! ;* r6 = channel out buffer ;* r7 = channel struct ;* channelBufferdCopy push r1 push r2 push r3 push r4 push r5 rqldi r7,channelCurrentPositionHigh rqldi r7,channelRepeatStart rqldi r7,channelRepeatLength ld r1 ;pos high ld r2 ;repeat start ld r3 ;repeat length rqldi r7,channelSampleAdrLow rqldi r7,channelSampleAdrHigh add r3,r3,r2 ;rep start + rep length ld r4 ;sample adr low ld r5 ;sample adr high nop esadr r5,r4 ;sample addr smpLoop rqldi r7,channelLength cmplo r1,r3 ;pos high < (rep start + rep length) movets r1,r1,r2 ;pos high = pos high TS else rep start , dont remove fractal part ld r4 ;channel length nop cmplo r1,r4 ;pos high < channel length brtc smpFinish movei r4,0 ;delay slot value = 0 rqldi r7,channelCurrentPositionLow ;delay slot rqldi r7,channelIncrement ;delay slot nop ;delay slot ld r5 ;pos low ld r4 ;increment nop ;? erqldb r1 ;take some cycles to get data add r5,r5,r4 ;pos + incremnt addtqi r1,r1,0 rqldi r7,channelVolume add r5,r5,r4 ;pos + increment addtqi r1,r1,0 ld r4 ;volume ssto channelCurrentPositionLow stwo r7,r5 ;store low back extri r5,0 ;is even address? eld r5 ;value nop swptc r5,r5 ;swap bytes smpFinish subi r0,1 extb r5,r5 ;signed extend from byte to word brts smpLoop muls r5,r5,r4 ;value * volume delay slot nop ; delay slot stinc r6,r5 ;*channelbuffer++ = value delay slot nop ; delay slot ssto channelCurrentPositionHigh stwo r7,r1 ;store high back rqpop rqpop rqpop pop r5 pop r4 pop r3 rqpop rqpop jmpi r5,0 ;return via r5! pop r2 ; delay slot pop r1 ; delay slot nop ; delay slot nop ; delay slot