1;;********** S3M Play Routine **********
2
3
4s3m_init
5	lea.l	data,a5
6	move.l	s3m(a5),a0
7	move.l	a0,mname(a5)
8	move	ordernum(a0),d0
9	iword	d0
10	move	d0,slen(a5)
11	move	d0,positioneita(a5)
12
13	move	patnum(a0),d0
14	iword	d0
15	move	d0,pats(a5)
16
17	move	insnum(a0),d0
18	iword	d0
19	move	d0,inss(a5)
20
21	move	ffv(a0),d0
22	iword	d0
23	move	d0,fformat(a5)
24
25	move	flags(a0),d0
26	iword	d0
27	move	d0,sflags(a5)
28
29	cmp	#$1301,fformat(a5)
30	bhi.b	.ok
31
32	bset	#6,sflags+1(a5)
33
34.ok	lea	$60(a0),a1
35	moveq	#0,d0
36	move	slen(a5),d0
37	moveq	#1,d1
38	and	d0,d1
39	add	d1,d0
40	lea	(a1,d0.l),a2
41	move.l	a2,samples(a5)
42
43	move	inss(a5),d0
44	add	d0,d0
45	lea	(a2,d0.l),a3
46	move.l	a3,patts(a5)
47
48	moveq	#0,d0
49	move.b	(a1),d0
50	add	d0,d0
51	sub.l	a1,a1
52	move	(a3,d0),d0
53	beq.b	.q
54	iword	d0
55	asl.l	#4,d0
56	lea	2(a0,d0.l),a1
57.q	move.l	a1,ppos(a5)
58
59	moveq	#0,d0
60	move.b	initialspeed(a0),d0
61	bne.b	.ok2
62	moveq	#6,d0
63.ok2	move	d0,spd(a5)
64
65	move.b	initialtempo(a0),d0
66	cmp	#32,d0
67	bhi.b	.qw
68	moveq	#125,d0
69.qw	move	d0,tempo(a5)
70
71	move	inss(a5),d0
72	subq	#1,d0
73	move.l	samples(a5),a2
74.instloop
75	moveq	#0,d1
76	move	(a2)+,d1
77	iword	d1
78	lsl.l	#4,d1
79	lea	(a0,d1.l),a1
80	btst	#0,insflags(a1)
81	beq.b	.eloo
82	move.l	insloopend(a1),d1
83	ilword	d1
84	cmp.l	#2,d1
85	bls.b	.eloo
86	move.l	insloopend(a1),inslength(a1)
87.eloo	dbf	d0,.instloop
88
89	clr	pos(a5)
90	clr	rows(a5)
91	clr	cn(a5)
92	clr	pdelaycnt(a5)
93	clr	pjmpflag(a5)
94	clr	pbrkflag(a5)
95	clr	pbrkrow(a5)
96
97	bsr	detectchannels
98
99	move.l	#14317056/4,clock(a5)		; Clock constant
100	move	#64,globalVol(a5)
101	moveq	#0,d0
102	rts
103
104
105s3m_music
106	lea	data,a5
107	move.l	s3m(a5),a0
108
109	addq	#1,cn(a5)
110	move	cn(a5),d0
111	cmp	spd(a5),d0
112	beq.b	uusrow
113
114ccmds	lea	c0(a5),a2
115	lea	cha0(a5),a4
116	move	numchans(a5),d7
117	subq	#1,d7
118.loo	btst	#7,5(a2)
119	beq.b	.edi
120
121	lea	cct(pc),a1
122	moveq	#0,d0
123	move.b	cmd(a2),d0
124	cmp	#'Z'-'@',d0
125	bhi.b	.edi
126	add	d0,d0
127	move	(a1,d0),d0
128	jsr	(a1,d0)
129
130.edi	lea	s3mChanBlock_SIZE(a2),a2
131	lea	mChanBlock_SIZE(a4),a4
132	dbf	d7,.loo
133	rts
134
135uusrow	clr	cn(a5)
136
137	tst	pdelaycnt(a5)
138	bne	process
139
140	lea	c0(a5),a2
141	move	numchans(a5),d7
142	subq	#1,d7
143.cl	clr.b	flgs(a2)
144	lea	s3mChanBlock_SIZE(a2),a2
145	dbf	d7,.cl
146
147	move.l	ppos(a5),a1
148	lea	c0(a5),a4		;chanblocks
149.loo	move.b	(a1)+,d0
150	beq.b	.end
151
152	moveq	#$1f,d5
153	and	d0,d5			;chan
154	mulu	#s3mChanBlock_SIZE,d5
155	lea	(a4,d5),a2
156
157	and	#~31,d0
158	move.b	d0,flgs(a2)
159
160	moveq	#32,d2
161	and	d0,d2
162	beq.b	.nnot
163
164	move.b	(a1)+,(a2)
165	move.b	(a1)+,inst(a2)
166
167.nnot	moveq	#64,d2
168	and	d0,d2
169	beq.b	.nvol
170
171	move.b	(a1)+,vol(a2)
172
173.nvol	and	#128,d0
174	beq.b	.loo
175
176	move.b	(a1)+,d0
177	bmi.b	.d
178	move.b	d0,cmd(a2)
179.d	move.b	(a1)+,info(a2)
180	bra.b	.loo
181
182.end	move.l	a1,ppos(a5)
183
184process	lea	c0(a5),a2
185	lea	cha0(a5),a4
186	move	numchans(a5),d7
187	move.l	samples(a5),a5
188	subq	#1,d7
189	endb	a5
190
191.lloo	tst.b	flgs(a2)
192	beq	.evol
193
194	moveq	#32,d0
195	and.b	flgs(a2),d0
196	beq	.f
197
198	move.b	inst(a2),d0
199	beq	.esmp
200	bmi	.esmp
201
202	cmp	inss,d0
203	bgt	.mute
204
205	btst	#7,flgs(a2)
206	beq.b	.eii
207	cmp.b	#'S'-'@',cmd(a2)
208	bne.b	.eii
209	move.b	info(a2),d1
210	and	#$f0,d1
211	cmp	#$d0,d1
212	beq	.evol
213
214.eii	add	d0,d0
215	move	-2(a5,d0),d0
216	iword	d0
217	lsl	#4,d0
218	lea	(a0,d0),a1
219
220	moveq	#0,d0
221	move	insmemseg(a1),d0
222	iword	d0
223	lsl.l	#4,d0
224	move.l	a0,d4
225	add.l	d0,d4
226
227	move.l	insloopbeg(a1),d1
228	ilword	d1
229	move.l	insloopend(a1),d2
230	ilword	d2
231	sub.l	d1,d2
232	add.l	d4,d1
233
234	move.l	d1,mLStart(a4)
235	move.l	d2,mLLength(a4)
236	move.b	insvol(a1),volume+1(a2)
237	cmp	#64,volume(a2)
238	blo.b	.e
239	move	#63,volume(a2)
240.e	move.l	a1,sample(a2)
241
242	btst	#0,insflags(a1)
243	beq.b	.eloo
244	cmp.l	#2,d2
245	shi	mLoop(a4)
246	bra.b	.esmp
247
248
249.mute	st	mOnOff(a4)
250	bra	.f
251
252.eloo	clr.b	mLoop(a4)
253.esmp	moveq	#0,d0
254	move.b	(a2),d0
255	beq	.f
256	cmp.b	#254,d0
257	beq.b	.mute
258	cmp.b	#255,d0
259	beq	.f
260
261	move.b	d0,note(a2)
262	move	d0,d1
263	lsr	#4,d1
264
265	and	#$f,d0
266	add	d0,d0
267
268	move.l	sample(a2),a1
269	move.l	$20(a1),d2
270	ilword	d2
271
272	lea	Periods(pc),a1
273	move	(a1,d0),d0
274	mulu	#8363,d0
275	lsl.l	#4,d0
276	lsr.l	d1,d0
277
278	divu	d2,d0
279
280
281	btst	#7,flgs(a2)
282	beq.b	.ei
283
284	cmp.b	#'Q'-'@',cmd(a2)	;retrig
285	beq.b	.eiik
286
287.ei	clr.b	retrigcn(a2)
288
289.eiik	clr.b	vibpos(a2)
290
291
292	btst	#7,flgs(a2)
293	beq.b	.eitopo
294
295	cmp.b	#'G'-'@',cmd(a2)	;TOPO
296	beq.b	.eddo
297
298	cmp.b	#'L'-'@',cmd(a2)	;TOPO+VSLD
299	bne.b	.eitopo
300
301.eddo	move	d0,toperiod(a2)
302	bra.b	.f
303
304.eitopo	move	d0,mPeriod(a4)
305	move	d0,period(a2)
306	clr.l	mFPos(a4)
307
308	move.l	sample(a2),d0
309	beq.b	.f
310	move.l	d0,a1
311
312	moveq	#0,d0
313	move	insmemseg(a1),d0
314	iword	d0
315	lsl.l	#4,d0
316	move.l	a0,d4
317	add.l	d0,d4
318
319	move.l	inslength(a1),d0
320	ilword	d0
321
322	move.l	d4,(a4)
323	move.l	d0,mLength(a4)
324	clr.b	mOnOff(a4)
325
326.f	moveq	#64,d0
327	and.b	flgs(a2),d0
328	beq.b	.evol
329	move.b	vol(a2),volume+1(a2)
330	cmp	#64,volume(a2)
331	blo.b	.evol
332	move	#63,volume(a2)
333
334.evol	btst	#7,flgs(a2)
335	beq.b	.eivib
336
337	cmp.b	#'H'-'@',cmd(a2)
338	beq.b	.vib
339
340.eivib	bsr	checklimits
341.vib
342
343	btst	#7,flgs(a2)
344	beq.b	.eitre
345
346	cmp.b	#'R'-'@',cmd(a2)
347	beq.b	.tre
348	cmp.b	#'I'-'@',cmd(a2)
349	beq.b	.tre
350
351.eitre	move	volume(a2),d0
352	mulu	globalVol,d0
353	lsr	#6,d0
354	move	d0,mVolume(a4)
355
356.tre	btst	#7,flgs(a2)
357	beq.b	.edd
358
359	move.b	info(a2),d0
360	beq.b	.dd
361	move.b	d0,lastcmd(a2)
362.dd	lea	ct(pc),a1
363	moveq	#0,d0
364	move.b	cmd(a2),d0
365	cmp	#'Z'-'@',d0
366	bhi.b	.edd
367
368	add	d0,d0
369	move	(a1,d0),d0
370	jsr	(a1,d0)
371
372.edd	lea	s3mChanBlock_SIZE(a2),a2
373	lea	mChanBlock_SIZE(a4),a4
374	dbf	d7,.lloo
375
376	basereg	data,a5
377	lea	data,a5
378
379	tst	pdelaycnt(a5)
380	beq.b	.oke
381
382	subq	#1,pdelaycnt(a5)
383	bra	xm_exit
384.oke
385	addq	#1,rows(a5)
386
387	tst	pbrkflag(a5)		; do we have to break this pattern?
388	beq.b	.nobrk
389	move	pbrkrow(a5),rows(a5)
390	clr	pbrkrow(a5)		; clr break position
391.nobrk
392	cmp	#64,rows(a5)
393	bcc.b	.newpos				; worst case opt: branch not taken
394
395	tst	pjmpflag(a5)		; do we have to jump?
396	bne.b	.newpos
397
398	tst	pbrkflag(a5)
399	beq	dee
400	bra.b	cont
401.newpos
402	move	pbrkrow(a5),rows(a5)
403	clr	pbrkrow(a5)		; clr break position
404
405burk	addq	#1,pos(a5)			; inc songposition
406	move	slen(a5),d0
407	cmp	pos(a5),d0			; are we thru with all patterns?
408	bgt.b	cont				; nope
409	clr	pos(a5)
410	st	PS3M_break(a5)
411
412	 move.l	#-1,uade_restart_cmd
413
414	moveq	#0,d0
415	move.b	initialspeed(a0),d0
416	bne.b	.ok
417	moveq	#6,d0
418.ok	move	d0,spd(a5)
419
420cont	move	pos(a5),d0
421	move	d0,PS3M_position(a5)
422	st	PS3M_poscha(a5)
423
424	moveq	#0,d1
425	move.b	orders(a0,d0),d1
426	cmp.b	#$fe,d1				; marker that is skipped
427	beq.b	burk
428	cmp.b	#$ff,d1				; end of tune mark
429	beq.b	burk
430	cmp	pats(a5),d1
431	bhs.b	burk
432
433	add	d1,d1
434	move.l	patts(a5),a3
435	moveq	#0,d0
436	move	(a3,d1),d0
437	beq.b	burk
438	iword	d0
439	lsl.l	#4,d0
440	lea	2(a0,d0.l),a1
441
442	clr	pjmpflag(a5)
443	clr	pbrkflag(a5)
444
445	move	rows(a5),d0
446	beq.b	.setp
447	subq	#1,d0
448	moveq	#0,d1
449.loop	move.b	(a1)+,d1
450	beq.b	.next
451
452	moveq	#32,d2
453	and	d1,d2
454	beq.b	.nnot
455	addq	#2,a1
456.nnot
457	moveq	#64,d2
458	and	d1,d2
459	beq.b	.nvol
460	addq	#1,a1
461.nvol
462	and	#128,d1
463	beq.b	.loop
464	addq	#2,a1
465
466	bra.b	.loop
467.next
468	dbf	d0,.loop
469.setp
470	move.l	a1,ppos(a5)
471
472dee	bra	xm_dee
473	endb	a5
474
475
476ct	dc	rt-ct
477	dc	changespeed-ct
478	dc	posjmp-ct
479	dc	patbrk-ct
480	dc	vslide-ct
481	dc	portadwn-ct
482	dc	portaup-ct
483	dc	rt-ct
484	dc	rt-ct
485	dc	tremor-ct
486	dc	arpeggio-ct
487	dc	rt-ct
488	dc	rt-ct
489	dc	rt-ct
490	dc	rt-ct
491	dc	soffset-ct
492	dc	rt-ct
493	dc	retrig-ct
494	dc	rt-ct
495	dc	specials-ct
496	dc	stempo-ct
497	dc	rt-ct
498	dc	setmaster-ct
499	dc	rt-ct
500	dc	rt-ct
501	dc	rt-ct
502	dc	rt-ct
503
504
505
506cct	dc	rt-cct
507	dc	rt-cct
508	dc	rt-cct
509	dc	rt-cct
510	dc	vslide-cct
511	dc	portadwn-cct
512	dc	portaup-cct
513	dc	noteporta-cct
514	dc	vibrato-cct
515	dc	tremor-cct
516	dc	arpeggio-cct
517	dc	vvslide-cct
518	dc	pvslide-cct
519	dc	rt-cct
520	dc	rt-cct
521	dc	rt-cct
522	dc	rt-cct
523	dc	retrig-cct
524	dc	tremolo-cct
525	dc	specials-cct
526	dc	rt-cct
527	dc	finevib-cct
528	dc	rt-cct
529	dc	rt-cct
530	dc	rt-cct
531	dc	rt-cct
532	dc	rt-cct
533
534tremolo
535rt	rts
536
537tremor
538	move.b	info(a2),d0
539	beq.b	.toggle
540	move.b	d0,tvalue(a2)
541.toggle
542	subq.b	#1,tcount(a2)
543	bhi.b	.volume
544	move.b	tvalue(a2),d0
545	not	ttoggle(a2)
546	beq.b	.off
547	lsr.b	#4,d0				; ontime
548.off	and.b	#$f,d0				; offtime
549	move.b	d0,tcount(a2)
550.volume
551	move	volume(a2),d0
552	and	ttoggle(a2),d0
553	move	d0,mVolume(a4)
554	rts
555
556changespeed
557	move.b	info(a2),d0
558	bne.b	.d
559	moveq	#6,d0
560.d	cmp.b	#32,d0
561	bcs.b	.e
562	moveq	#31,d0
563.e	move.b	d0,spd+1
564	rts
565
566posjmp	clr	pbrkrow
567	st	pjmpflag
568
569	moveq	#0,d0
570	move.b	pos,d0
571	addq	#1,d0
572
573	cmp	slen,d0
574	bne.b	.notlast
575	st	PS3M_break
576.notlast
577	moveq	#0,d0
578	move.b	info(a2),d0
579	cmp	pos,d0
580	bhi.b	.e
581	st	PS3M_break
582.e	subq	#1,d0
583	move	d0,pos
584	st	PS3M_poscha
585	rts
586
587patbrk	moveq	#0,d0
588	move.b	info(a2),d0
589	moveq	#$f,d2
590	and	d0,d2
591	lsr	#4,d0
592	add.b	.dtab(pc,d0),d2
593	cmp.b	#63,d2		; valid line number given?
594	ble.b	.ok
595	moveq	#0,d2		; else zero it
596.ok	move	d2,pbrkrow
597	st	pjmpflag
598	st	PS3M_poscha
599	rts
600
601.dtab:	dc.b	0,10,20,30	; Don't think this little table is a waste!
602	dc.b 	40,50,60,70	; The routine is shorter using this table
603	dc.b	80,90,100,110	; and faster too :-)
604	dc.b 	120,130,140,150	; 16 bytes vs. 8 instructions (wordlength)
605
606vslide	moveq	#0,d0
607	move.b	lastcmd(a2),d0
608	moveq	#$f,d1
609	and	d0,d1
610	move	d0,d2
611	lsr	#4,d2
612
613	cmp.b	#$f,d1
614	beq.b	.addfine
615
616	cmp.b	#$f,d2
617	beq.b	.subfine
618
619	btst	#6,sflags+1
620	bne.b	.ok
621
622	tst	cn
623	beq.b	.dd
624
625.ok	tst	d1
626	beq.b	.add
627	and	#$f,d0
628	bra.b	.sub
629
630.subfine
631	tst	cn
632	bne.b	.dd
633	and	#$f,d0
634.sub	sub	d0,volume(a2)
635	bpl.b	.dd
636	clr	volume(a2)
637.dd	move	volume(a2),d0
638	mulu	globalVol,d0
639	lsr	#6,d0
640	move	d0,mVolume(a4)
641	rts
642
643.addfine
644	tst	d2
645	beq.b	.sub
646	tst	cn
647	bne.b	.dd
648.add	lsr	#4,d0
649
650.add2	add	d0,volume(a2)
651	cmp	#64,volume(a2)
652	blo.b	.dd
653	move	#63,volume(a2)
654	bra.b	.dd
655
656
657portadwn
658	moveq	#0,d0
659	move.b	lastcmd(a2),d0
660
661	tst	cn
662	beq.b	.fined
663	cmp.b	#$e0,d0
664	bhs.b	.dd
665	lsl	#2,d0
666
667.ddd	add	d0,period(a2)
668	bra.b	checklimits
669.dd	rts
670
671.fined	cmp.b	#$e0,d0
672	bls.b	.dd
673	cmp.b	#$f0,d0
674	bls.b	.extr
675	and	#$f,d0
676	lsl	#2,d0
677	bra.b	.ddd
678
679.extr	and	#$f,d0
680	bra.b	.ddd
681
682portaup
683	moveq	#0,d0
684	move.b	lastcmd(a2),d0
685
686	tst	cn
687	beq.b	.fined
688	cmp.b	#$e0,d0
689	bhs.b	.dd
690	lsl	#2,d0
691
692.ddd	sub	d0,period(a2)
693	bra.b	checklimits
694
695.dd	rts
696
697.fined	cmp.b	#$e0,d0
698	bls.b	.dd
699	cmp.b	#$f0,d0
700	bls.b	.extr
701	and	#$f,d0
702	lsl	#2,d0
703	bra.b	.ddd
704
705.extr	and	#$f,d0
706	bra.b	.ddd
707
708
709checklimits
710	move	period(a2),d0
711	btst	#4,sflags+1
712	beq.b	.sii
713
714	cmp	#856*4,d0
715	bls.b	.dd
716	move	#856*4,d0
717.dd	cmp	#113*4,d0
718	bhs.b	.dd2
719	move	#113*4,d0
720.dd2	move	d0,period(a2)
721	move	d0,mPeriod(a4)
722	rts
723
724.sii	cmp	#$7fff,d0
725	bls.b	.dd3
726	move	#$7fff,d0
727.dd3	cmp	#64,d0
728	bhs.b	.dd4
729	move	#64,d0
730.dd4	move	d0,mPeriod(a4)
731	rts
732
733
734noteporta
735	move.b	info(a2),d0
736	beq.b	notchange
737	move.b	d0,notepspd(a2)
738notchange
739	move	toperiod(a2),d0
740	beq.b	.1
741	moveq	#0,d1
742	move.b	notepspd(a2),d1
743	lsl	#2,d1
744
745	cmp	period(a2),d0
746	blt.b	.topoup
747
748	add	d1,period(a2)
749	cmp	period(a2),d0
750	bgt.b	.1
751	move	d0,period(a2)
752	clr	toperiod(a2)
753.1	move	period(a2),mPeriod(a4)
754	rts
755
756.topoup	sub	d1,period(a2)
757	cmp	period(a2),d0
758	blt.b	.dd
759	move	d0,period(a2)
760	clr	toperiod(a2)
761.dd	move	period(a2),mPeriod(a4)
762	rts
763
764
765vibrato	move.b	cmd(a2),d0
766	bne.b	.e
767	move.b	vibcmd(a2),d0
768	bra.b	.skip2
769
770.e	move	d0,d1
771	and	#$f0,d1
772	bne.b	.skip2
773
774	move.b	vibcmd(a2),d1
775	and	#$f0,d1
776	or	d1,d0
777
778.skip2
779	move.b	d0,vibcmd(a2)
780
781vibrato2
782	moveq	#$1f,d0
783	and.b	vibpos(a2),d0
784	moveq	#0,d2
785	lea	mt_vibratotable(pc),a3
786	move.b	(a3,d0),d2
787	moveq	#$f,d0
788	and.b	vibcmd(a2),d0
789	mulu	d0,d2
790
791	moveq	#4,d0
792	btst	#0,sflags+1
793	bne.b	.sii
794	moveq	#5,d0
795.sii	lsr	d0,d2
796	move	period(a2),d0
797	btst	#5,vibpos(a2)
798	bne.b	.neg
799	add	d2,d0
800	bra.b	.vib3
801.neg
802	sub	d2,d0
803.vib3
804	move	d0,mPeriod(a4)
805	move.b	vibcmd(a2),d0
806	lsr.b	#4,d0
807	add.b	d0,vibpos(a2)
808	rts
809
810
811finevib	move.b	cmd(a2),d0
812	bne.b	.e
813	move.b	vibcmd(a2),d0
814	bra.b	.skip2
815
816.e	move	d0,d1
817	and	#$f0,d1
818	bne.b	.skip2
819
820	move.b	vibcmd(a2),d1
821	and	#$f0,d1
822	or	d1,d0
823
824.skip2
825	move.b	d0,vibcmd(a2)
826	moveq	#$1f,d0
827	and.b	vibpos(a2),d0
828	moveq	#0,d2
829	lea	mt_vibratotable(pc),a3
830	move.b	(a3,d0),d2
831	moveq	#$f,d0
832	and.b	vibcmd(a2),d0
833	mulu	d0,d2
834
835	lsr	#7,d2
836	move	period(a2),d0
837	btst	#5,vibpos(a2)
838	bne.b	.neg
839	add	d2,d0
840	bra.b	.vib3
841.neg	sub	d2,d0
842.vib3	move	d0,mPeriod(a4)
843	move.b	vibcmd(a2),d0
844	lsr.b	#4,d0
845	add.b	d0,vibpos(a2)
846	rts
847
848
849arpeggio
850	moveq	#0,d0
851	move.b	note(a2),d0
852	beq.b	.qq
853
854	moveq	#$70,d1
855	and	d0,d1
856	and	#$f,d0
857
858	moveq	#0,d2
859	move	cn,d2
860	divu	#3,d2
861	swap	d2
862	tst	d2
863	beq.b	.norm
864	subq	#1,d2
865	beq.b	.1
866
867	moveq	#$f,d2
868	and.b	lastcmd(a2),d2
869	add	d2,d0
870.f	cmp	#12,d0
871	blt.b	.norm
872	sub	#12,d0
873	add	#$10,d1
874	bra.b	.f
875
876.1	move.b	lastcmd(a2),d2
877	lsr.b	#4,d2
878	add.b	d2,d0
879.f2	cmp	#12,d0
880	blt.b	.norm
881	sub	#12,d0
882	add	#$10,d1
883	bra.b	.f2
884
885.norm	add	d0,d0
886	lsr	#4,d1
887
888	move.l	sample(a2),a1
889
890	move.l	$20(a1),d2
891	ilword	d2
892
893	lea	Periods(pc),a1
894	move	(a1,d0),d0
895	mulu	#8363,d0
896	lsl.l	#4,d0
897	lsr.l	d1,d0
898	divu	d2,d0
899	move	d0,mPeriod(a4)
900.qq	rts
901
902
903pvslide	bsr	notchange
904	bra	vslide
905
906vvslide	bsr	vibrato2
907	bra	vslide
908
909soffset	moveq	#32,d0
910	and.b	flgs(a2),d0
911	beq	.f
912	move.b	(a2),d0
913	beq	.f
914	cmp.b	#255,d0
915	beq	.f
916
917	move.l	sample(a2),d0
918	beq.b	.f
919	move.l	d0,a1
920
921	moveq	#0,d0
922	move	insmemseg(a1),d0
923	iword	d0
924	lsl.l	#4,d0
925	move.l	a0,d4
926	add.l	d0,d4
927
928	move.l	inslength(a1),d0
929	ilword	d0
930
931	moveq	#0,d2
932	move.b	lastcmd(a2),d2
933	lsl.l	#8,d2
934	add.l	d2,d4
935	sub.l	d2,d0
936	bpl.b	.ok
937	move.l	mLStart(a4),d4
938	move.l	mLLength(a4),d0
939.ok	move.l	d4,(a4)
940	move.l	d0,mLength(a4)
941.f	rts
942
943
944retrig	move.b	retrigcn(a2),d0
945	subq.b	#1,d0
946	cmp.b	#0,d0
947	ble.b	.retrig
948
949	move.b	d0,retrigcn(a2)
950	rts
951
952.retrig	move.l	sample(a2),d0
953	beq	.f
954	move.l	d0,a1
955	moveq	#0,d1
956	move	insmemseg(a1),d1
957	iword	d1
958	lsl.l	#4,d1
959	move.l	a0,d4
960	add.l	d1,d4
961
962	move.l	inslength(a1),d1
963	ilword	d1
964
965	move.l	d4,(a4)
966	move.l	d1,mLength(a4)
967	clr.b	mOnOff(a4)
968	clr.l	mFPos(a4)
969
970	move.b	lastcmd(a2),d0
971	moveq	#$f,d1
972	and.b	d0,d1
973	move.b	d1,retrigcn(a2)
974
975	and	#$f0,d0
976	lsr	#4,d0
977	lea	ftab2(pc),a3
978	moveq	#0,d2
979	move.b	(a3,d0),d2
980	beq.b	.ddq
981
982	mulu	volume(a2),d2
983	lsr	#4,d2
984	move	d2,volume(a2)
985	bra.b	.ddw
986
987.ddq	lea	ftab1(pc),a3
988	move.b	(a3,d0),d2
989	ext	d2
990	add	d2,volume(a2)
991
992.ddw	tst	volume(a2)
993	bpl.b	.ei0
994	clr	volume(a2)
995.ei0	cmp	#64,volume(a2)
996	blo.b	.ei64
997	move	#63,volume(a2)
998.ei64	move	volume(a2),d0
999	mulu	globalVol,d0
1000	lsr	#6,d0
1001	move	d0,mVolume(a4)
1002.f	rts
1003
1004; NOTE: All subroutines expect the command parameter (the x of Fx, that is) in d0!
1005specials
1006	move.b	info(a2),d1
1007	moveq	#$f,d0
1008	and	d1,d0
1009	and	#$f0,d1
1010	cmp	#$b0,d1
1011	beq.b	.ploop
1012	cmp	#$d0,d1
1013	beq.b	.delay
1014	cmp	#$e0,d1
1015	beq.b	.pdelay
1016	cmp	#$c0,d1
1017	bne.b	.dd
1018
1019	cmp	cn,d0
1020	bne.b	.dd
1021	clr	volume(a2)
1022	clr	mVolume(a4)
1023.dd	rts
1024
1025.ploop	tst	cn
1026	bne.b	.dd
1027
1028	tst	d0
1029	beq.b	.setlp			; 0 means "set loop mark" in current line
1030
1031	tst	loopcnt(a2)		; dont allow nesting, accept value
1032	beq.b	.jcnt			; only if we counted down the last loop
1033
1034	subq	#1,loopcnt(a2)		; count down
1035	bne.b	.jloop			; jump again if still not zero
1036	rts
1037.jcnt	move	d0,loopcnt(a2)		; accept new loop value
1038.jloop	move	looprow(a2),pbrkrow	; put line number to jump to
1039	st	pbrkflag
1040	rts
1041.setlp	move	rows,looprow(a2)
1042	rts
1043
1044.pdelay	tst	cn
1045	bne.b	.dd
1046
1047	tst	pdelaycnt
1048	bne.b	.skip
1049
1050	move	d0,pdelaycnt
1051.skip	rts
1052
1053.delay	cmp	cn,d0
1054	bne.b	.dd
1055
1056	moveq	#32,d0
1057	and.b	flgs(a2),d0
1058	beq	.f
1059
1060	move.b	inst(a2),d0
1061	beq	.esmp
1062	bmi	.esmp
1063
1064	cmp	inss,d0
1065	bgt	.dd
1066
1067	move.l	samples,a5
1068	add	d0,d0
1069	move	-2(a5,d0),d0
1070	iword	d0
1071	asl	#4,d0
1072	lea	(a0,d0),a1
1073
1074	moveq	#0,d0
1075	move	insmemseg(a1),d0
1076	iword	d0
1077	asl.l	#4,d0
1078	move.l	a0,d4
1079	add.l	d0,d4
1080
1081	move.l	insloopbeg(a1),d1
1082	ilword	d1
1083	move.l	insloopend(a1),d2
1084	ilword	d2
1085	sub.l	d1,d2
1086	add.l	d4,d1
1087
1088	move.l	inslength(a1),d0
1089	ilword	d0
1090
1091	move.l	d4,(a4)
1092	move.l	d0,mLength(a4)
1093	move.l	d1,mLStart(a4)
1094	move.l	d2,mLLength(a4)
1095	move.b	insvol(a1),volume+1(a2)
1096	cmp	#64,volume(a2)
1097	blo.b	.e
1098	move	#63,volume(a2)
1099.e	clr.b	mOnOff(a4)
1100
1101	move.l	a1,sample(a2)
1102
1103	btst	#0,insflags(a1)
1104	bne.b	.loo
1105	clr.b	mLoop(a4)
1106	bra.b	.esmp
1107.loo	cmp.l	#2,d2
1108	shi	mLoop(a4)
1109
1110.esmp	moveq	#0,d0
1111	move.b	(a2),d0
1112	beq.b	.f
1113	bmi.b	.f
1114
1115	moveq	#$70,d1
1116	and	d0,d1
1117	lsr	#4,d1
1118
1119	and	#$f,d0
1120	add	d0,d0
1121
1122	move.l	sample(a2),a1
1123
1124	move.l	$20(a1),d2
1125	ilword	d2
1126
1127	lea	Periods(pc),a1
1128	move	(a1,d0),d0
1129	mulu	#8363,d0
1130	lsl.l	#4,d0
1131	lsr.l	d1,d0
1132	divu	d2,d0
1133
1134	move	d0,mPeriod(a4)
1135	move	d0,period(a2)
1136	clr.l	mFPos(a4)
1137	clr.b	vibpos(a2)
1138
1139.f	moveq	#64,d0
1140	and.b	flgs(a2),d0
1141	beq.b	.evol
1142	move.b	vol(a2),volume+1(a2)
1143	cmp	#64,volume(a2)
1144	blo.b	.evol
1145	move	#63,volume(a2)
1146.evol	move	volume(a2),d0
1147	mulu	globalVol,d0
1148	lsr	#6,d0
1149	move	d0,mVolume(a4)
1150	rts
1151
1152
1153stempo	moveq	#0,d0
1154	move.b	info(a2),d0
1155	cmp	#32,d0
1156	bls.b	.e
1157	move.l	mrate,d1
1158	move.l	d1,d2
1159	lsl.l	#2,d1
1160	add.l	d2,d1
1161	add	d0,d0
1162	divu	d0,d1
1163
1164	addq	#1,d1
1165	and	#~1,d1
1166	move	d1,bytesperframe
1167.e	rts
1168
1169setmaster
1170	moveq	#0,d0
1171	move.b	info(a2),d0
1172	cmp	#64,d0
1173	bls.b	.d
1174	moveq	#64,d0
1175.d	move	d0,globalVol
1176	rts
1177
1178Periods
1179 dc	1712,1616,1524,1440,1356,1280,1208,1140,1076,1016,960,907
1180
1181ftab1	dc.b	0,-1,-2,-4,-8,-16,0,0
1182	dc.b	0,1,2,4,8,16,0,0
1183
1184ftab2	dc.b	0,0,0,0,0,0,10,8
1185	dc.b	0,0,0,0,0,0,24,32
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195