1 /*	MikMod sound library
2 	(c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
3 	for complete list.
4 
5 	This library is free software; you can redistribute it and/or modify
6 	it under the terms of the GNU Library General Public License as
7 	published by the Free Software Foundation; either version 2 of
8 	the License, or (at your option) any later version.
9 
10 	This program is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 	GNU Library General Public License for more details.
14 
15 	You should have received a copy of the GNU Library General Public
16 	License along with this library; if not, write to the Free Software
17 	Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 	02111-1307, USA.
19 */
20 
21 /*==============================================================================
22 
23   $Id$
24 
25   The Protracker Player Driver
26 
27   The protracker driver supports all base Protracker 3.x commands and features.
28 
29 ==============================================================================*/
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include <string.h>
36 #include <stdarg.h>
37 #ifdef SRANDOM_IN_MATH_H
38 #include <math.h>
39 #else
40 #include <stdlib.h>
41 #endif
42 
43 #include "mikmod_internals.h"
44 
45 #ifdef SUNOS
46 extern int fprintf(FILE *, const char *, ...);
47 extern long int random(void);
48 #endif
49 
50 /* The currently playing module */
51 /* This variable should better be static, but it would break the ABI, so this
52    will wait */
53 /*static*/ MODULE *pf = NULL;
54 
55 #define	HIGH_OCTAVE		2	/* number of above-range octaves */
56 
57 static	UWORD oldperiods[OCTAVE*2]={
58 	0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80,
59 	0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0,
60 	0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160,
61 	0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700
62 };
63 
64 static	UBYTE VibratoTable[32]={
65 	  0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253,
66 	255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24
67 };
68 
69 static	UBYTE avibtab[128]={
70 	 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23,
71 	24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44,
72 	45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58,
73 	59,59,60,60,61,61,62,62,62,63,63,63,63,63,63,63,
74 	64,63,63,63,63,63,63,63,62,62,62,61,61,60,60,59,
75 	59,58,57,57,56,55,54,54,53,52,51,50,49,48,47,46,
76 	45,44,42,41,40,39,38,36,35,34,32,31,30,28,27,25,
77 	24,23,21,20,18,17,15,14,12,10, 9, 7, 6, 4, 3, 1
78 };
79 
80 /* Triton's linear periods to frequency translation table (for XM modules) */
81 static	ULONG lintab[768]={
82 	535232,534749,534266,533784,533303,532822,532341,531861,
83 	531381,530902,530423,529944,529466,528988,528511,528034,
84 	527558,527082,526607,526131,525657,525183,524709,524236,
85 	523763,523290,522818,522346,521875,521404,520934,520464,
86 	519994,519525,519057,518588,518121,517653,517186,516720,
87 	516253,515788,515322,514858,514393,513929,513465,513002,
88 	512539,512077,511615,511154,510692,510232,509771,509312,
89 	508852,508393,507934,507476,507018,506561,506104,505647,
90 	505191,504735,504280,503825,503371,502917,502463,502010,
91 	501557,501104,500652,500201,499749,499298,498848,498398,
92 	497948,497499,497050,496602,496154,495706,495259,494812,
93 	494366,493920,493474,493029,492585,492140,491696,491253,
94 	490809,490367,489924,489482,489041,488600,488159,487718,
95 	487278,486839,486400,485961,485522,485084,484647,484210,
96 	483773,483336,482900,482465,482029,481595,481160,480726,
97 	480292,479859,479426,478994,478562,478130,477699,477268,
98 	476837,476407,475977,475548,475119,474690,474262,473834,
99 	473407,472979,472553,472126,471701,471275,470850,470425,
100 	470001,469577,469153,468730,468307,467884,467462,467041,
101 	466619,466198,465778,465358,464938,464518,464099,463681,
102 	463262,462844,462427,462010,461593,461177,460760,460345,
103 	459930,459515,459100,458686,458272,457859,457446,457033,
104 	456621,456209,455797,455386,454975,454565,454155,453745,
105 	453336,452927,452518,452110,451702,451294,450887,450481,
106 	450074,449668,449262,448857,448452,448048,447644,447240,
107 	446836,446433,446030,445628,445226,444824,444423,444022,
108 	443622,443221,442821,442422,442023,441624,441226,440828,
109 	440430,440033,439636,439239,438843,438447,438051,437656,
110 	437261,436867,436473,436079,435686,435293,434900,434508,
111 	434116,433724,433333,432942,432551,432161,431771,431382,
112 	430992,430604,430215,429827,429439,429052,428665,428278,
113 	427892,427506,427120,426735,426350,425965,425581,425197,
114 	424813,424430,424047,423665,423283,422901,422519,422138,
115 	421757,421377,420997,420617,420237,419858,419479,419101,
116 	418723,418345,417968,417591,417214,416838,416462,416086,
117 	415711,415336,414961,414586,414212,413839,413465,413092,
118 	412720,412347,411975,411604,411232,410862,410491,410121,
119 	409751,409381,409012,408643,408274,407906,407538,407170,
120 	406803,406436,406069,405703,405337,404971,404606,404241,
121 	403876,403512,403148,402784,402421,402058,401695,401333,
122 	400970,400609,400247,399886,399525,399165,398805,398445,
123 	398086,397727,397368,397009,396651,396293,395936,395579,
124 	395222,394865,394509,394153,393798,393442,393087,392733,
125 	392378,392024,391671,391317,390964,390612,390259,389907,
126 	389556,389204,388853,388502,388152,387802,387452,387102,
127 	386753,386404,386056,385707,385359,385012,384664,384317,
128 	383971,383624,383278,382932,382587,382242,381897,381552,
129 	381208,380864,380521,380177,379834,379492,379149,378807,
130 	378466,378124,377783,377442,377102,376762,376422,376082,
131 	375743,375404,375065,374727,374389,374051,373714,373377,
132 	373040,372703,372367,372031,371695,371360,371025,370690,
133 	370356,370022,369688,369355,369021,368688,368356,368023,
134 	367691,367360,367028,366697,366366,366036,365706,365376,
135 	365046,364717,364388,364059,363731,363403,363075,362747,
136 	362420,362093,361766,361440,361114,360788,360463,360137,
137 	359813,359488,359164,358840,358516,358193,357869,357547,
138 	357224,356902,356580,356258,355937,355616,355295,354974,
139 	354654,354334,354014,353695,353376,353057,352739,352420,
140 	352103,351785,351468,351150,350834,350517,350201,349885,
141 	349569,349254,348939,348624,348310,347995,347682,347368,
142 	347055,346741,346429,346116,345804,345492,345180,344869,
143 	344558,344247,343936,343626,343316,343006,342697,342388,
144 	342079,341770,341462,341154,340846,340539,340231,339924,
145 	339618,339311,339005,338700,338394,338089,337784,337479,
146 	337175,336870,336566,336263,335959,335656,335354,335051,
147 	334749,334447,334145,333844,333542,333242,332941,332641,
148 	332341,332041,331741,331442,331143,330844,330546,330247,
149 	329950,329652,329355,329057,328761,328464,328168,327872,
150 	327576,327280,326985,326690,326395,326101,325807,325513,
151 	325219,324926,324633,324340,324047,323755,323463,323171,
152 	322879,322588,322297,322006,321716,321426,321136,320846,
153 	320557,320267,319978,319690,319401,319113,318825,318538,
154 	318250,317963,317676,317390,317103,316817,316532,316246,
155 	315961,315676,315391,315106,314822,314538,314254,313971,
156 	313688,313405,313122,312839,312557,312275,311994,311712,
157 	311431,311150,310869,310589,310309,310029,309749,309470,
158 	309190,308911,308633,308354,308076,307798,307521,307243,
159 	306966,306689,306412,306136,305860,305584,305308,305033,
160 	304758,304483,304208,303934,303659,303385,303112,302838,
161 	302565,302292,302019,301747,301475,301203,300931,300660,
162 	300388,300117,299847,299576,299306,299036,298766,298497,
163 	298227,297958,297689,297421,297153,296884,296617,296349,
164 	296082,295815,295548,295281,295015,294749,294483,294217,
165 	293952,293686,293421,293157,292892,292628,292364,292100,
166 	291837,291574,291311,291048,290785,290523,290261,289999,
167 	289737,289476,289215,288954,288693,288433,288173,287913,
168 	287653,287393,287134,286875,286616,286358,286099,285841,
169 	285583,285326,285068,284811,284554,284298,284041,283785,
170 	283529,283273,283017,282762,282507,282252,281998,281743,
171 	281489,281235,280981,280728,280475,280222,279969,279716,
172 	279464,279212,278960,278708,278457,278206,277955,277704,
173 	277453,277203,276953,276703,276453,276204,275955,275706,
174 	275457,275209,274960,274712,274465,274217,273970,273722,
175 	273476,273229,272982,272736,272490,272244,271999,271753,
176 	271508,271263,271018,270774,270530,270286,270042,269798,
177 	269555,269312,269069,268826,268583,268341,268099,267857
178 };
179 
180 #define LOGFAC 2*16
181 static	UWORD logtab[104]={
182 	LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,
183 	LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
184 	LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,
185 	LOGFAC*832,LOGFAC*826,LOGFAC*820,LOGFAC*814,
186 	LOGFAC*808,LOGFAC*802,LOGFAC*796,LOGFAC*791,
187 	LOGFAC*785,LOGFAC*779,LOGFAC*774,LOGFAC*768,
188 	LOGFAC*762,LOGFAC*757,LOGFAC*752,LOGFAC*746,
189 	LOGFAC*741,LOGFAC*736,LOGFAC*730,LOGFAC*725,
190 	LOGFAC*720,LOGFAC*715,LOGFAC*709,LOGFAC*704,
191 	LOGFAC*699,LOGFAC*694,LOGFAC*689,LOGFAC*684,
192 	LOGFAC*678,LOGFAC*675,LOGFAC*670,LOGFAC*665,
193 	LOGFAC*660,LOGFAC*655,LOGFAC*651,LOGFAC*646,
194 	LOGFAC*640,LOGFAC*636,LOGFAC*632,LOGFAC*628,
195 	LOGFAC*623,LOGFAC*619,LOGFAC*614,LOGFAC*610,
196 	LOGFAC*604,LOGFAC*601,LOGFAC*597,LOGFAC*592,
197 	LOGFAC*588,LOGFAC*584,LOGFAC*580,LOGFAC*575,
198 	LOGFAC*570,LOGFAC*567,LOGFAC*563,LOGFAC*559,
199 	LOGFAC*555,LOGFAC*551,LOGFAC*547,LOGFAC*543,
200 	LOGFAC*538,LOGFAC*535,LOGFAC*532,LOGFAC*528,
201 	LOGFAC*524,LOGFAC*520,LOGFAC*516,LOGFAC*513,
202 	LOGFAC*508,LOGFAC*505,LOGFAC*502,LOGFAC*498,
203 	LOGFAC*494,LOGFAC*491,LOGFAC*487,LOGFAC*484,
204 	LOGFAC*480,LOGFAC*477,LOGFAC*474,LOGFAC*470,
205 	LOGFAC*467,LOGFAC*463,LOGFAC*460,LOGFAC*457,
206 	LOGFAC*453,LOGFAC*450,LOGFAC*447,LOGFAC*443,
207 	LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
208 };
209 
210 static	SBYTE PanbrelloTable[256]={
211 	  0,  2,  3,  5,  6,  8,  9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
212 	 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
213 	 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
214 	 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
215 	 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
216 	 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
217 	 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
218 	 24, 23, 22, 20, 19, 17, 16, 14, 12, 11,  9,  8,  6,  5,  3,  2,
219 	  0,- 2,- 3,- 5,- 6,- 8,- 9,-11,-12,-14,-16,-17,-19,-20,-22,-23,
220 	-24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44,
221 	-45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59,
222 	-59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64,
223 	-64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60,
224 	-59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46,
225 	-45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26,
226 	-24,-23,-22,-20,-19,-17,-16,-14,-12,-11,- 9,- 8,- 6,- 5,- 3,- 2
227 };
228 
229 /* returns a random value between 0 and ceil-1, ceil must be a power of two */
getrandom(int ceil)230 static int getrandom(int ceil)
231 {
232 #ifdef HAVE_SRANDOM
233 	return random()&(ceil-1);
234 #else
235 	return (rand()*ceil)/(RAND_MAX+1.0);
236 #endif
237 }
238 
239 /*	New Note Action Scoring System :
240 	--------------------------------
241 	1)	total-volume (fadevol, chanvol, volume) is the main scorer.
242 	2)	a looping sample is a bonus x2
243 	3)	a foreground channel is a bonus x4
244 	4)	an active envelope with keyoff is a handicap -x2
245 */
MP_FindEmptyChannel(MODULE * mod)246 static int MP_FindEmptyChannel(MODULE *mod)
247 {
248 	MP_VOICE *a;
249 	ULONG t,k,tvol,pp;
250 
251 	for (t=0;t<md_sngchn;t++)
252 		if (((mod->voice[t].main.kick==KICK_ABSENT)||
253 			 (mod->voice[t].main.kick==KICK_ENV))&&
254 		   Voice_Stopped_internal(t))
255 			return t;
256 
257 	tvol=0xffffffUL;t=-1;a=mod->voice;
258 	for (k=0;k<md_sngchn;k++,a++) {
259 		/* allow us to take over a nonexisting sample */
260 		if (!a->main.s)
261 			return k;
262 
263 		if ((a->main.kick==KICK_ABSENT)||(a->main.kick==KICK_ENV)) {
264 			pp=a->totalvol<<((a->main.s->flags&SF_LOOP)?1:0);
265 			if ((a->master)&&(a==a->master->slave))
266 				pp<<=2;
267 
268 			if (pp<tvol) {
269 				tvol=pp;
270 				t=k;
271 			}
272 		}
273 	}
274 
275 	if (tvol>8000*7) return -1;
276 	return t;
277 }
278 
Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)279 static SWORD Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)
280 {
281 	if ((p1==p2)||(p==p1)) return v1;
282 	return v1+((SLONG)((p-p1)*(v2-v1))/(p2-p1));
283 }
284 
getlinearperiod(UWORD note,ULONG fine)285 UWORD getlinearperiod(UWORD note,ULONG fine)
286 {
287 	UWORD t;
288 
289 	t=((20L+2*HIGH_OCTAVE)*OCTAVE+2-note)*32L-(fine>>1);
290 	return t;
291 }
292 
getlogperiod(UWORD note,ULONG fine)293 static UWORD getlogperiod(UWORD note,ULONG fine)
294 {
295 	UWORD n,o;
296 	UWORD p1,p2;
297 	ULONG i;
298 
299 	n=note%(2*OCTAVE);
300 	o=note/(2*OCTAVE);
301 	i=(n<<2)+(fine>>4); /* n*8 + fine/16 */
302 
303 	p1=logtab[i];
304 	p2=logtab[i+1];
305 
306 	return (Interpolate(fine>>4,0,15,p1,p2)>>o);
307 }
308 
getoldperiod(UWORD note,ULONG speed)309 static UWORD getoldperiod(UWORD note,ULONG speed)
310 {
311 	UWORD n,o;
312 
313 	/* This happens sometimes on badly converted AMF, and old MOD */
314 	if (!speed) {
315 #ifdef MIKMOD_DEBUG
316 		fprintf(stderr,"\rmplayer: getoldperiod() called with note=%d, speed=0 !\n",note);
317 #endif
318 		return 4242; /* <- prevent divide overflow.. (42 hehe) */
319 	}
320 
321 	n=note%(2*OCTAVE);
322 	o=note/(2*OCTAVE);
323 	return ((8363L*(ULONG)oldperiods[n])>>o)/speed;
324 }
325 
GetPeriod(UWORD flags,UWORD note,ULONG speed)326 static UWORD GetPeriod(UWORD flags, UWORD note, ULONG speed)
327 {
328 	if (flags & UF_XMPERIODS) {
329 		if (flags & UF_LINEAR)
330 				return getlinearperiod(note, speed);
331 		else
332 				return getlogperiod(note, speed);
333 	} else
334 		return getoldperiod(note, speed);
335 }
336 
InterpolateEnv(SWORD p,ENVPT * a,ENVPT * b)337 static SWORD InterpolateEnv(SWORD p,ENVPT *a,ENVPT *b)
338 {
339 	return (Interpolate(p,a->pos,b->pos,a->val,b->val));
340 }
341 
DoPan(SWORD envpan,SWORD pan)342 static SWORD DoPan(SWORD envpan,SWORD pan)
343 {
344 	int newpan;
345 
346 	newpan=pan+(((envpan-PAN_CENTER)*(128-abs(pan-PAN_CENTER)))/128);
347 
348 	return (newpan<PAN_LEFT)?PAN_LEFT:(newpan>PAN_RIGHT?PAN_RIGHT:newpan);
349 }
350 
StartEnvelope(ENVPR * t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT * p,UBYTE keyoff)351 static SWORD StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT *p,UBYTE keyoff)
352 {
353 	t->flg=flg;
354 	t->pts=pts;
355 	t->susbeg=susbeg;
356 	t->susend=susend;
357 	t->beg=beg;
358 	t->end=end;
359 	t->env=p;
360 	t->p=0;
361 	t->a=0;
362 	t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1;
363 
364 	/* Imago Orpheus sometimes stores an extra initial point in the envelope */
365 	if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) {
366 		t->a++;t->b++;
367 	}
368 
369 	/* Fit in the envelope, still */
370 	if (t->a >= t->pts)
371 		t->a = t->pts - 1;
372 	if (t->b >= t->pts)
373 		t->b = t->pts-1;
374 
375 	return t->env[t->a].val;
376 }
377 
378 /* This procedure processes all envelope types, include volume, pitch, and
379    panning.  Envelopes are defined by a set of points, each with a magnitude
380    [relating either to volume, panning position, or pitch modifier] and a tick
381    position.
382 
383    Envelopes work in the following manner:
384 
385    (a) Each tick the envelope is moved a point further in its progression. For
386        an accurate progression, magnitudes between two envelope points are
387        interpolated.
388 
389    (b) When progression reaches a defined point on the envelope, values are
390        shifted to interpolate between this point and the next, and checks for
391        loops or envelope end are done.
392 
393    Misc:
394      Sustain loops are loops that are only active as long as the keyoff flag is
395      clear.  When a volume envelope terminates, so does the current fadeout.
396 */
ProcessEnvelope(MP_VOICE * aout,ENVPR * t,SWORD v)397 static SWORD ProcessEnvelope(MP_VOICE *aout, ENVPR *t, SWORD v)
398 {
399 	if (t->flg & EF_ON) {
400 		UBYTE a, b;		/* actual points in the envelope */
401 		UWORD p;		/* the 'tick counter' - real point being played */
402 
403 		a = t->a;
404 		b = t->b;
405 		p = t->p;
406 
407 		/*
408 		 * Sustain loop on one point (XM type).
409 		 * Not processed if KEYOFF.
410 		 * Don't move and don't interpolate when the point is reached
411 		 */
412 		if ((t->flg & EF_SUSTAIN) && t->susbeg == t->susend &&
413 		   (!(aout->main.keyoff & KEY_OFF) && p == t->env[t->susbeg].pos)) {
414 			v = t->env[t->susbeg].val;
415 		} else {
416 			/*
417 			 * All following situations will require interpolation between
418 			 * two envelope points.
419 			 */
420 
421 			/*
422 			 * Sustain loop between two points (IT type).
423 			 * Not processed if KEYOFF.
424 			 */
425 			/* if we were on a loop point, loop now */
426 			if ((t->flg & EF_SUSTAIN) && !(aout->main.keyoff & KEY_OFF) &&
427 			   a >= t->susend) {
428 				a = t->susbeg;
429 				b = (t->susbeg==t->susend)?a:a+1;
430 				p = t->env[a].pos;
431 				v = t->env[a].val;
432 			} else
433 			/*
434 			 * Regular loop.
435 			 * Be sure to correctly handle single point loops.
436 			 */
437 			if ((t->flg & EF_LOOP) && a >= t->end) {
438 				a = t->beg;
439 				b = t->beg == t->end ? a : a + 1;
440 				p = t->env[a].pos;
441 				v = t->env[a].val;
442 			} else
443 			/*
444 			 * Non looping situations.
445 			 */
446 			if (a != b)
447 				v = InterpolateEnv(p, &t->env[a], &t->env[b]);
448 			else
449 				v = t->env[a].val;
450 
451 			/*
452 			 * Start to fade if the volume envelope is finished.
453 			 */
454 			if (p >= t->env[t->pts - 1].pos) {
455 				if (t->flg & EF_VOLENV) {
456 					aout->main.keyoff |= KEY_FADE;
457 					if (!v)
458 						aout->main.fadevol = 0;
459 				}
460 			} else {
461 				p++;
462 				/* did pointer reach point b? */
463 				if (p >= t->env[b].pos)
464 					a = b++; /* shift points a and b */
465 			}
466 			t->a = a;
467 			t->b = b;
468 			t->p = p;
469 		}
470 	}
471 	return v;
472 }
473 
474 /* XM linear period to frequency conversion */
getfrequency(UWORD flags,ULONG period)475 ULONG getfrequency(UWORD flags,ULONG period)
476 {
477 	if (flags & UF_LINEAR) {
478 		SLONG shift = ((SLONG)period / 768) - HIGH_OCTAVE;
479 
480 		if (shift >= 0)
481 			return lintab[period % 768] >> shift;
482 		else
483 			return lintab[period % 768] << (-shift);
484 	} else
485 		return (8363L*1712L)/(period?period:1);
486 }
487 
488 /*========== Protracker effects */
489 
DoArpeggio(UWORD tick,UWORD flags,MP_CONTROL * a,UBYTE style)490 static void DoArpeggio(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE style)
491 {
492 	UBYTE note=a->main.note;
493 
494 	if (a->arpmem) {
495 		switch (style) {
496 		case 0:		/* mod style: N, N+x, N+y */
497 			switch (tick % 3) {
498 			/* case 0: unchanged */
499 			case 1:
500 				note += (a->arpmem >> 4);
501 				break;
502 			case 2:
503 				note += (a->arpmem & 0xf);
504 				break;
505 			}
506 			break;
507 		case 3:		/* okt arpeggio 3: N-x, N, N+y */
508 			switch (tick % 3) {
509 			case 0:
510 				note -= (a->arpmem >> 4);
511 				break;
512 			/* case 1: unchanged */
513 			case 2:
514 				note += (a->arpmem & 0xf);
515 				break;
516 			}
517 			break;
518 		case 4:		/* okt arpeggio 4: N, N+y, N, N-x */
519 			switch (tick % 4) {
520 			/* case 0, case 2: unchanged */
521 			case 1:
522 				note += (a->arpmem & 0xf);
523 				break;
524 			case 3:
525 				note -= (a->arpmem >> 4);
526 				break;
527 			}
528 			break;
529 		case 5:		/* okt arpeggio 5: N-x, N+y, N, and nothing at tick 0 */
530 			if (!tick)
531 				break;
532 			switch (tick % 3) {
533 			/* case 0: unchanged */
534 			case 1:
535 				note -= (a->arpmem >> 4);
536 				break;
537 			case 2:
538 				note += (a->arpmem & 0xf);
539 				break;
540 			}
541 			break;
542 		}
543 		a->main.period = GetPeriod(flags, (UWORD)note << 1, a->speed);
544 		a->ownper = 1;
545 	}
546 }
547 
DoPTEffect0(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)548 static int DoPTEffect0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
549 {
550 	UBYTE dat;
551 
552 	(void)mod; /* unused arg */
553 	(void)channel; /* unused arg */
554 
555 	dat = UniGetByte();
556 	if (!tick) {
557 		if (!dat && (flags & UF_ARPMEM))
558 			dat=a->arpmem;
559 		else
560 			a->arpmem=dat;
561 	}
562 	if (a->main.period)
563 		DoArpeggio(tick, flags, a, 0);
564 
565 	return 0;
566 }
567 
DoPTEffect1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)568 static int DoPTEffect1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
569 {
570 	UBYTE dat;
571 
572 	(void)flags; /* unused arg */
573 	(void)mod; /* unused arg */
574 	(void)channel; /* unused arg */
575 
576 	dat = UniGetByte();
577 	if (!tick && dat)
578 		a->slidespeed = (UWORD)dat << 2;
579 	if (a->main.period)
580 		if (tick)
581 			a->tmpperiod -= a->slidespeed;
582 
583 	return 0;
584 }
585 
DoPTEffect2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)586 static int DoPTEffect2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
587 {
588 	UBYTE dat;
589 
590 	(void)flags; /* unused arg */
591 	(void)mod; /* unused arg */
592 	(void)channel; /* unused arg */
593 
594 	dat = UniGetByte();
595 	if (!tick && dat)
596 		a->slidespeed = (UWORD)dat << 2;
597 	if (a->main.period)
598 		if (tick)
599 			a->tmpperiod += a->slidespeed;
600 
601 	return 0;
602 }
603 
DoToneSlide(UWORD tick,MP_CONTROL * a)604 static void DoToneSlide(UWORD tick, MP_CONTROL *a)
605 {
606 	if (!a->main.fadevol)
607 		a->main.kick = (a->main.kick == KICK_NOTE)? KICK_NOTE : KICK_KEYOFF;
608 	else
609 		a->main.kick = (a->main.kick == KICK_NOTE)? KICK_ENV : KICK_ABSENT;
610 
611 	if (tick != 0) {
612 		int dist;
613 
614 		/* We have to slide a->main.period towards a->wantedperiod, so compute
615 		   the difference between those two values */
616 		dist=a->main.period-a->wantedperiod;
617 
618 		/* if they are equal or if portamentospeed is too big ...*/
619 		if (dist == 0 || a->portspeed > abs(dist))
620 			/* ...make tmpperiod equal tperiod */
621 			a->tmpperiod=a->main.period=a->wantedperiod;
622 		else if (dist>0) {
623 			a->tmpperiod-=a->portspeed;
624 			a->main.period-=a->portspeed; /* dist>0, slide up */
625 		} else {
626 			a->tmpperiod+=a->portspeed;
627 			a->main.period+=a->portspeed; /* dist<0, slide down */
628 		}
629 	} else
630 		a->tmpperiod=a->main.period;
631 	a->ownper = 1;
632 }
633 
DoPTEffect3(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)634 static int DoPTEffect3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
635 {
636 	UBYTE dat;
637 
638 	(void)flags; /* unused arg */
639 	(void)mod; /* unused arg */
640 	(void)channel; /* unused arg */
641 
642 	dat=UniGetByte();
643 	if ((!tick)&&(dat)) a->portspeed=(UWORD)dat<<2;
644 	if (a->main.period)
645 		DoToneSlide(tick, a);
646 
647 	return 0;
648 }
649 
DoVibrato(UWORD tick,MP_CONTROL * a)650 static void DoVibrato(UWORD tick, MP_CONTROL *a)
651 {
652 	UBYTE q;
653 	UWORD temp = 0;	/* silence warning */
654 
655 	if (!tick)
656 		return;
657 
658 	q=(a->vibpos>>2)&0x1f;
659 
660 	switch (a->wavecontrol&3) {
661 	case 0: /* sine */
662 		temp=VibratoTable[q];
663 		break;
664 	case 1: /* ramp down */
665 		q<<=3;
666 		if (a->vibpos<0) q=255-q;
667 		temp=q;
668 		break;
669 	case 2: /* square wave */
670 		temp=255;
671 		break;
672 	case 3: /* random wave */
673 		temp=getrandom(256);
674 		break;
675 	}
676 
677 	temp*=a->vibdepth;
678 	temp>>=7;temp<<=2;
679 
680 	if (a->vibpos>=0)
681 		a->main.period=a->tmpperiod+temp;
682 	else
683 		a->main.period=a->tmpperiod-temp;
684 	a->ownper = 1;
685 
686 	if (tick != 0)
687 		a->vibpos+=a->vibspd;
688 }
689 
DoPTEffect4(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)690 static int DoPTEffect4(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
691 {
692 	UBYTE dat;
693 
694 	(void)flags; /* unused arg */
695 	(void)mod; /* unused arg */
696 	(void)channel; /* unused arg */
697 
698 	dat=UniGetByte();
699 	if (!tick) {
700 		if (dat&0x0f) a->vibdepth=dat&0xf;
701 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
702 	}
703 	if (a->main.period)
704 		DoVibrato(tick, a);
705 
706 	return 0;
707 }
708 
DoVolSlide(MP_CONTROL * a,UBYTE dat)709 static void DoVolSlide(MP_CONTROL *a, UBYTE dat)
710 {
711 	if (dat&0xf) {
712 		a->tmpvolume-=(dat&0x0f);
713 		if (a->tmpvolume<0)
714 			a->tmpvolume=0;
715 	} else {
716 		a->tmpvolume+=(dat>>4);
717 		if (a->tmpvolume>64)
718 			a->tmpvolume=64;
719 	}
720 }
721 
DoPTEffect5(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)722 static int DoPTEffect5(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
723 {
724 	UBYTE dat;
725 
726 	(void)flags; /* unused arg */
727 	(void)mod; /* unused arg */
728 	(void)channel; /* unused arg */
729 
730 	dat=UniGetByte();
731 	if (a->main.period)
732 		DoToneSlide(tick, a);
733 
734 	if (tick)
735 		DoVolSlide(a, dat);
736 
737 	return 0;
738 }
739 
740 /* DoPTEffect6 after DoPTEffectA */
741 
DoPTEffect7(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)742 static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
743 {
744 	UBYTE dat;
745 	UBYTE q;
746 	UWORD temp = 0;	/* silence warning */
747 
748 	(void)flags; /* unused arg */
749 	(void)mod; /* unused arg */
750 	(void)channel; /* unused arg */
751 
752 	dat=UniGetByte();
753 	if (!tick) {
754 		if (dat&0x0f) a->trmdepth=dat&0xf;
755 		if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
756 	}
757 	if (a->main.period) {
758 		q=(a->trmpos>>2)&0x1f;
759 
760 		switch ((a->wavecontrol>>4)&3) {
761 		case 0: /* sine */
762 			temp=VibratoTable[q];
763 			break;
764 		case 1: /* ramp down */
765 			q<<=3;
766 			if (a->trmpos<0) q=255-q;
767 			temp=q;
768 			break;
769 		case 2: /* square wave */
770 			temp=255;
771 			break;
772 		case 3: /* random wave */
773 			temp=getrandom(256);
774 			break;
775 		}
776 		temp*=a->trmdepth;
777 		temp>>=6;
778 
779 		if (a->trmpos>=0) {
780 			a->volume=a->tmpvolume+temp;
781 			if (a->volume>64) a->volume=64;
782 		} else {
783 			a->volume=a->tmpvolume-temp;
784 			if (a->volume<0) a->volume=0;
785 		}
786 		a->ownvol = 1;
787 
788 		if (tick)
789 			a->trmpos+=a->trmspd;
790 	}
791 
792 	return 0;
793 }
794 
DoPTEffect8(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)795 static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
796 {
797 	UBYTE dat;
798 
799 	(void)tick; /* unused arg */
800 	(void)flags; /* unused arg */
801 
802 	dat = UniGetByte();
803 	if (mod->panflag)
804 		a->main.panning = mod->panning[channel] = dat;
805 
806 	return 0;
807 }
808 
DoPTEffect9(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)809 static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
810 {
811 	UBYTE dat;
812 
813 	(void)flags; /* unused arg */
814 	(void)mod; /* unused arg */
815 	(void)channel; /* unused arg */
816 
817 	dat=UniGetByte();
818 	if (!tick) {
819 		if (dat) a->soffset=(UWORD)dat<<8;
820 		a->main.start=a->hioffset|a->soffset;
821 
822 		if ((a->main.s)&&(a->main.start>a->main.s->length))
823 			a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
824 			    a->main.s->loopstart:a->main.s->length;
825 	}
826 
827 	return 0;
828 }
829 
DoPTEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)830 static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
831 {
832 	UBYTE dat;
833 
834 	(void)flags; /* unused arg */
835 	(void)mod; /* unused arg */
836 	(void)channel; /* unused arg */
837 
838 	dat=UniGetByte();
839 	if (tick)
840 		DoVolSlide(a, dat);
841 
842 	return 0;
843 }
844 
DoPTEffect6(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)845 static int DoPTEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
846 {
847 	if (a->main.period)
848 		DoVibrato(tick, a);
849 	DoPTEffectA(tick, flags, a, mod, channel);
850 
851 	return 0;
852 }
853 
DoPTEffectB(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)854 static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
855 {
856 	UBYTE dat;
857 
858 	(void)a; /* unused arg */
859 	(void)channel; /* unused arg */
860 
861 	dat=UniGetByte();
862 
863 	if (tick || mod->patdly2)
864 		return 0;
865 
866 	/* Vincent Voois uses a nasty trick in "Universal Bolero" */
867 	if (dat == mod->sngpos && mod->patbrk == mod->patpos)
868 		return 0;
869 
870 	if (!mod->loop && !mod->patbrk &&
871 	    (dat < mod->sngpos ||
872 		 (mod->sngpos == (mod->numpos - 1) && !mod->patbrk) ||
873 	     (dat == mod->sngpos && (flags & UF_NOWRAP))
874 		)) {
875 		/* if we don't loop, better not to skip the end of the
876 		   pattern, after all... so:
877 		mod->patbrk=0; */
878 		mod->posjmp=3;
879 	} else {
880 		/* if we were fading, adjust... */
881 		if (mod->sngpos == (mod->numpos-1))
882 			mod->volume=mod->initvolume>128?128:mod->initvolume;
883 		mod->sngpos=dat;
884 		mod->posjmp=2;
885 		mod->patpos=0;
886 	}
887 
888 	return 0;
889 }
890 
DoPTEffectC(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)891 static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
892 {
893 	UBYTE dat;
894 
895 	(void)flags; /* unused arg */
896 	(void)mod; /* unused arg */
897 	(void)channel; /* unused arg */
898 
899 			dat=UniGetByte();
900 			if (tick) return 0;
901 			if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
902 			else if (dat>64) dat=64;
903 			a->tmpvolume=dat;
904 
905 	return 0;
906 }
907 
DoPTEffectD(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)908 static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
909 {
910 	UBYTE dat;
911 
912 	(void)a; /* unused arg */
913 	(void)channel; /* unused arg */
914 
915 			dat=UniGetByte();
916 			if ((tick)||(mod->patdly2)) return 0;
917 			if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&&
918 			   (dat>mod->pattrows[mod->positions[mod->sngpos]]))
919 				dat=mod->pattrows[mod->positions[mod->sngpos]];
920 			mod->patbrk=dat;
921 			if (!mod->posjmp) {
922 				/* don't ask me to explain this code - it makes
923 				   backwards.s3m and children.xm (heretic's version) play
924 				   correctly, among others. Take that for granted, or write
925 				   the page of comments yourself... you might need some
926 				   aspirin - Miod */
927 				if ((mod->sngpos==mod->numpos-1)&&(dat)&&((mod->loop)||
928 				               (mod->positions[mod->sngpos]==(mod->numpat-1)
929 								&& !(flags&UF_NOWRAP)))) {
930 					mod->sngpos=0;
931 					mod->posjmp=2;
932 				} else
933 					mod->posjmp=3;
934 			}
935 
936 	return 0;
937 }
938 
DoEEffects(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel,UBYTE dat)939 static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod,
940 	SWORD channel, UBYTE dat)
941 {
942 	UBYTE nib = dat & 0xf;
943 
944 	switch (dat>>4) {
945 	case 0x0: /* hardware filter toggle, not supported */
946 		break;
947 	case 0x1: /* fineslide up */
948 		if (a->main.period)
949 			if (!tick)
950 				a->tmpperiod-=(nib<<2);
951 		break;
952 	case 0x2: /* fineslide dn */
953 		if (a->main.period)
954 			if (!tick)
955 				a->tmpperiod+=(nib<<2);
956 		break;
957 	case 0x3: /* glissando ctrl */
958 		a->glissando=nib;
959 		break;
960 	case 0x4: /* set vibrato waveform */
961 		a->wavecontrol&=0xf0;
962 		a->wavecontrol|=nib;
963 		break;
964 	case 0x5: /* set finetune */
965 		if (a->main.period) {
966 			if (flags&UF_XMPERIODS)
967 				a->speed=nib+128;
968 			else
969 				a->speed=finetune[nib];
970 			a->tmpperiod=GetPeriod(flags, (UWORD)a->main.note<<1,a->speed);
971 		}
972 		break;
973 	case 0x6: /* set patternloop */
974 		if (tick)
975 			break;
976 		if (nib) { /* set reppos or repcnt ? */
977 			/* set repcnt, so check if repcnt already is set, which means we
978 			   are already looping */
979 			if (a->pat_repcnt)
980 				a->pat_repcnt--; /* already looping, decrease counter */
981 			else {
982 #if 0
983 				/* this would make walker.xm, shipped with Xsoundtracker,
984 				   play correctly, but it's better to remain compatible
985 				   with FT2 */
986 				if ((!(flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))
987 #endif
988 					a->pat_repcnt=nib; /* not yet looping, so set repcnt */
989 			}
990 
991 			if (a->pat_repcnt) { /* jump to reppos if repcnt>0 */
992 				if (a->pat_reppos==POS_NONE)
993 					a->pat_reppos=mod->patpos-1;
994 				if (a->pat_reppos==-1) {
995 					mod->pat_repcrazy=1;
996 					mod->patpos=0;
997 				} else
998 					mod->patpos=a->pat_reppos;
999 			} else a->pat_reppos=POS_NONE;
1000 		} else
1001 			a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */
1002 		break;
1003 	case 0x7: /* set tremolo waveform */
1004 		a->wavecontrol&=0x0f;
1005 		a->wavecontrol|=nib<<4;
1006 		break;
1007 	case 0x8: /* set panning */
1008 		if (mod->panflag) {
1009 			if (nib<=8) nib<<=4;
1010 			else nib*=17;
1011 			a->main.panning=mod->panning[channel]=nib;
1012 		}
1013 		break;
1014 	case 0x9: /* retrig note */
1015 		/* do not retrigger on tick 0, until we are emulating FT2 and effect
1016 		   data is zero */
1017 		if (!tick && !((flags & UF_FT2QUIRKS) && (!nib)))
1018 			break;
1019 		/* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */
1020 		if (nib || !tick) {
1021 			if (!a->retrig) {
1022 				/* when retrig counter reaches 0, reset counter and restart
1023 				   the sample */
1024 				if (a->main.period) a->main.kick=KICK_NOTE;
1025 				a->retrig=nib;
1026 			}
1027 			a->retrig--; /* countdown */
1028 		}
1029 		break;
1030 	case 0xa: /* fine volume slide up */
1031 		if (tick)
1032 			break;
1033 		a->tmpvolume+=nib;
1034 		if (a->tmpvolume>64) a->tmpvolume=64;
1035 		break;
1036 	case 0xb: /* fine volume slide dn  */
1037 		if (tick)
1038 			break;
1039 		a->tmpvolume-=nib;
1040 		if (a->tmpvolume<0)a->tmpvolume=0;
1041 		break;
1042 	case 0xc: /* cut note */
1043 		/* When tick reaches the cut-note value, turn the volume to
1044 		   zero (just like on the amiga) */
1045 		if (tick>=nib)
1046 			a->tmpvolume=0; /* just turn the volume down */
1047 		break;
1048 	case 0xd: /* note delay */
1049 		/* delay the start of the sample until tick==nib */
1050 		if (!tick)
1051 			a->main.notedelay=nib;
1052 		else if (a->main.notedelay)
1053 			a->main.notedelay--;
1054 		break;
1055 	case 0xe: /* pattern delay */
1056 		if (!tick)
1057 			if (!mod->patdly2)
1058 				mod->patdly=nib+1; /* only once, when tick=0 */
1059 		break;
1060 	case 0xf: /* invert loop, not supported  */
1061 		break;
1062 	}
1063 }
1064 
DoPTEffectE(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1065 static int DoPTEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1066 {
1067 	DoEEffects(tick, flags, a, mod, channel, UniGetByte());
1068 
1069 	return 0;
1070 }
1071 
DoPTEffectF(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1072 static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1073 {
1074 	UBYTE dat;
1075 
1076 	(void)flags; /* unused arg */
1077 	(void)a; /* unused arg */
1078 	(void)channel; /* unused arg */
1079 
1080 	dat=UniGetByte();
1081 	if (tick||mod->patdly2) return 0;
1082 	if (mod->extspd&&(dat>=mod->bpmlimit))
1083 		mod->bpm=dat;
1084 	else
1085 	  if (dat) {
1086 		mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat;
1087 		mod->vbtick=0;
1088 	}
1089 
1090 	return 0;
1091 }
1092 
1093 /*========== Scream Tracker effects */
1094 
DoS3MEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1095 static int DoS3MEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1096 {
1097 	UBYTE speed;
1098 
1099 	(void)flags; /* unused arg */
1100 	(void)a; /* unused arg */
1101 	(void)channel; /* unused arg */
1102 
1103 	speed = UniGetByte();
1104 
1105 	if (tick || mod->patdly2)
1106 		return 0;
1107 
1108 	if (speed > 128)
1109 		speed -= 128;
1110 	if (speed) {
1111 		mod->sngspd = speed;
1112 		mod->vbtick = 0;
1113 	}
1114 
1115 	return 0;
1116 }
1117 
DoS3MVolSlide(UWORD tick,UWORD flags,MP_CONTROL * a,UBYTE inf)1118 static void DoS3MVolSlide(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE inf)
1119 {
1120 	UBYTE lo, hi;
1121 
1122 	if (inf)
1123 		a->s3mvolslide=inf;
1124 	else
1125 		inf=a->s3mvolslide;
1126 
1127 	lo=inf&0xf;
1128 	hi=inf>>4;
1129 
1130 	if (!lo) {
1131 		if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume+=hi;
1132 	} else
1133 	  if (!hi) {
1134 		if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume-=lo;
1135 	} else
1136 	  if (lo==0xf) {
1137 		if (!tick) a->tmpvolume+=(hi?hi:0xf);
1138 	} else
1139 	  if (hi==0xf) {
1140 		if (!tick) a->tmpvolume-=(lo?lo:0xf);
1141 	} else
1142 	  return;
1143 
1144 	if (a->tmpvolume<0)
1145 		a->tmpvolume=0;
1146 	else if (a->tmpvolume>64)
1147 		a->tmpvolume=64;
1148 }
1149 
DoS3MEffectD(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1150 static int DoS3MEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1151 {
1152 	(void)mod; /* unused arg */
1153 	(void)channel; /* unused arg */
1154 
1155 	DoS3MVolSlide(tick, flags, a, UniGetByte());
1156 
1157 	return 1;
1158 }
1159 
DoS3MSlideDn(UWORD tick,MP_CONTROL * a,UBYTE inf)1160 static void DoS3MSlideDn(UWORD tick, MP_CONTROL *a, UBYTE inf)
1161 {
1162 	UBYTE hi,lo;
1163 
1164 	if (inf)
1165 		a->slidespeed=inf;
1166 	else
1167 		inf=a->slidespeed;
1168 
1169 	hi=inf>>4;
1170 	lo=inf&0xf;
1171 
1172 	if (hi==0xf) {
1173 		if (!tick) a->tmpperiod+=(UWORD)lo<<2;
1174 	} else
1175 	  if (hi==0xe) {
1176 		if (!tick) a->tmpperiod+=lo;
1177 	} else {
1178 		if (tick) a->tmpperiod+=(UWORD)inf<<2;
1179 	}
1180 }
1181 
DoS3MEffectE(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1182 static int DoS3MEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1183 {
1184 	UBYTE dat;
1185 
1186 	(void)flags; /* unused arg */
1187 	(void)mod; /* unused arg */
1188 	(void)channel; /* unused arg */
1189 
1190 	dat=UniGetByte();
1191 	if (a->main.period)
1192 		DoS3MSlideDn(tick, a,dat);
1193 
1194 	return 0;
1195 }
1196 
DoS3MSlideUp(UWORD tick,MP_CONTROL * a,UBYTE inf)1197 static void DoS3MSlideUp(UWORD tick, MP_CONTROL *a, UBYTE inf)
1198 {
1199 	UBYTE hi,lo;
1200 
1201 	if (inf) a->slidespeed=inf;
1202 	else inf=a->slidespeed;
1203 
1204 	hi=inf>>4;
1205 	lo=inf&0xf;
1206 
1207 	if (hi==0xf) {
1208 		if (!tick) a->tmpperiod-=(UWORD)lo<<2;
1209 	} else
1210 	  if (hi==0xe) {
1211 		if (!tick) a->tmpperiod-=lo;
1212 	} else {
1213 		if (tick) a->tmpperiod-=(UWORD)inf<<2;
1214 	}
1215 }
1216 
DoS3MEffectF(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1217 static int DoS3MEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1218 {
1219 	UBYTE dat;
1220 
1221 	(void)flags; /* unused arg */
1222 	(void)mod; /* unused arg */
1223 	(void)channel; /* unused arg */
1224 
1225 	dat=UniGetByte();
1226 	if (a->main.period)
1227 		DoS3MSlideUp(tick, a,dat);
1228 
1229 	return 0;
1230 }
1231 
DoS3MEffectI(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1232 static int DoS3MEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1233 {
1234 	UBYTE inf, on, off;
1235 
1236 	(void)flags; /* unused arg */
1237 	(void)mod; /* unused arg */
1238 	(void)channel; /* unused arg */
1239 
1240 	inf = UniGetByte();
1241 	if (inf)
1242 		a->s3mtronof = inf;
1243 	else {
1244 		inf = a->s3mtronof;
1245 		if (!inf)
1246 			return 0;
1247 	}
1248 
1249 	if (!tick)
1250 		return 0;
1251 
1252 	on=(inf>>4)+1;
1253 	off=(inf&0xf)+1;
1254 	a->s3mtremor%=(on+off);
1255 	a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1256 	a->ownvol=1;
1257 	a->s3mtremor++;
1258 
1259 	return 0;
1260 }
1261 
DoS3MEffectQ(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1262 static int DoS3MEffectQ(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1263 {
1264 	UBYTE inf;
1265 
1266 	(void)mod; /* unused arg */
1267 	(void)channel; /* unused arg */
1268 
1269 	inf = UniGetByte();
1270 	if (a->main.period) {
1271 		if (inf) {
1272 			a->s3mrtgslide=inf>>4;
1273 			a->s3mrtgspeed=inf&0xf;
1274 		}
1275 
1276 		/* only retrigger if low nibble > 0 */
1277 		if (a->s3mrtgspeed>0) {
1278 			if (!a->retrig) {
1279 				/* when retrig counter reaches 0, reset counter and restart the
1280 				   sample */
1281 				if (a->main.kick!=KICK_NOTE) a->main.kick=KICK_KEYOFF;
1282 				a->retrig=a->s3mrtgspeed;
1283 
1284 				if ((tick)||(flags&UF_S3MSLIDES)) {
1285 					switch (a->s3mrtgslide) {
1286 					case 1:
1287 					case 2:
1288 					case 3:
1289 					case 4:
1290 					case 5:
1291 						a->tmpvolume-=(1<<(a->s3mrtgslide-1));
1292 						break;
1293 					case 6:
1294 						a->tmpvolume=(2*a->tmpvolume)/3;
1295 						break;
1296 					case 7:
1297 						a->tmpvolume>>=1;
1298 						break;
1299 					case 9:
1300 					case 0xa:
1301 					case 0xb:
1302 					case 0xc:
1303 					case 0xd:
1304 						a->tmpvolume+=(1<<(a->s3mrtgslide-9));
1305 						break;
1306 					case 0xe:
1307 						a->tmpvolume=(3*a->tmpvolume)>>1;
1308 						break;
1309 					case 0xf:
1310 						a->tmpvolume=a->tmpvolume<<1;
1311 						break;
1312 					}
1313 					if (a->tmpvolume<0)
1314 						a->tmpvolume=0;
1315 					else if (a->tmpvolume>64)
1316 						a->tmpvolume=64;
1317 				}
1318 			}
1319 			a->retrig--; /* countdown  */
1320 		}
1321 	}
1322 
1323 	return 0;
1324 }
1325 
DoS3MEffectR(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1326 static int DoS3MEffectR(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1327 {
1328 	UBYTE dat, q;
1329 	UWORD temp=0;	/* silence warning */
1330 
1331 	(void)flags; /* unused arg */
1332 	(void)mod; /* unused arg */
1333 	(void)channel; /* unused arg */
1334 
1335 	dat = UniGetByte();
1336 	if (!tick) {
1337 		if (dat&0x0f) a->trmdepth=dat&0xf;
1338 		if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
1339 	}
1340 
1341 	q=(a->trmpos>>2)&0x1f;
1342 
1343 	switch ((a->wavecontrol>>4)&3) {
1344 	case 0: /* sine */
1345 		temp=VibratoTable[q];
1346 		break;
1347 	case 1: /* ramp down */
1348 		q<<=3;
1349 		if (a->trmpos<0) q=255-q;
1350 		temp=q;
1351 		break;
1352 	case 2: /* square wave */
1353 		temp=255;
1354 		break;
1355 	case 3: /* random */
1356 		temp=getrandom(256);
1357 		break;
1358 	}
1359 
1360 	temp*=a->trmdepth;
1361 	temp>>=7;
1362 
1363 	if (a->trmpos>=0) {
1364 		a->volume=a->tmpvolume+temp;
1365 		if (a->volume>64) a->volume=64;
1366 	} else {
1367 		a->volume=a->tmpvolume-temp;
1368 		if (a->volume<0) a->volume=0;
1369 	}
1370 	a->ownvol = 1;
1371 
1372 	if (tick)
1373 		a->trmpos+=a->trmspd;
1374 
1375 	return 0;
1376 }
1377 
DoS3MEffectT(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1378 static int DoS3MEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1379 {
1380 	UBYTE tempo;
1381 
1382 	(void)flags; /* unused arg */
1383 	(void)a; /* unused arg */
1384 	(void)channel; /* unused arg */
1385 
1386 	tempo = UniGetByte();
1387 
1388 	if (tick || mod->patdly2)
1389 		return 0;
1390 
1391 	mod->bpm = (tempo < 32) ? 32 : tempo;
1392 
1393 	return 0;
1394 }
1395 
DoS3MEffectU(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1396 static int DoS3MEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1397 {
1398 	UBYTE dat, q;
1399 	UWORD temp = 0;	/* silence warning */
1400 
1401 	(void)flags; /* unused arg */
1402 	(void)mod; /* unused arg */
1403 	(void)channel; /* unused arg */
1404 
1405 	dat = UniGetByte();
1406 	if (!tick) {
1407 		if (dat&0x0f) a->vibdepth=dat&0xf;
1408 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1409 	} else
1410 		if (a->main.period) {
1411 			q=(a->vibpos>>2)&0x1f;
1412 
1413 			switch (a->wavecontrol&3) {
1414 			case 0: /* sine */
1415 				temp=VibratoTable[q];
1416 				break;
1417 			case 1: /* ramp down */
1418 				q<<=3;
1419 				if (a->vibpos<0) q=255-q;
1420 				temp=q;
1421 				break;
1422 			case 2: /* square wave */
1423 				temp=255;
1424 				break;
1425 			case 3: /* random */
1426 				temp=getrandom(256);
1427 				break;
1428 			}
1429 
1430 			temp*=a->vibdepth;
1431 			temp>>=8;
1432 
1433 			if (a->vibpos>=0)
1434 				a->main.period=a->tmpperiod+temp;
1435 			else
1436 				a->main.period=a->tmpperiod-temp;
1437 			a->ownper = 1;
1438 
1439 			a->vibpos+=a->vibspd;
1440 	}
1441 
1442 	return 0;
1443 }
1444 
1445 /*========== Envelope helpers */
1446 
DoKeyOff(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1447 static int DoKeyOff(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1448 {
1449 	(void)tick; /* unused arg */
1450 	(void)flags; /* unused arg */
1451 	(void)mod; /* unused arg */
1452 	(void)channel; /* unused arg */
1453 
1454 	a->main.keyoff|=KEY_OFF;
1455 	if ((!(a->main.volflg&EF_ON))||(a->main.volflg&EF_LOOP))
1456 		a->main.keyoff=KEY_KILL;
1457 
1458 	return 0;
1459 }
1460 
DoKeyFade(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1461 static int DoKeyFade(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1462 {
1463 	UBYTE dat;
1464 
1465 	(void)flags; /* unused arg */
1466 	(void)channel; /* unused arg */
1467 
1468 	dat=UniGetByte();
1469 	if ((tick>=dat)||(tick==mod->sngspd-1)) {
1470 		a->main.keyoff=KEY_KILL;
1471 		if (!(a->main.volflg&EF_ON))
1472 			a->main.fadevol=0;
1473 	}
1474 
1475 	return 0;
1476 }
1477 
1478 /*========== Fast Tracker effects */
1479 
1480 /* DoXMEffect6 after DoXMEffectA */
1481 
DoXMEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1482 static int DoXMEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1483 {
1484 	UBYTE inf, lo, hi;
1485 
1486 	(void)flags; /* unused arg */
1487 	(void)mod; /* unused arg */
1488 	(void)channel; /* unused arg */
1489 
1490 	inf = UniGetByte();
1491 	if (inf)
1492 		a->s3mvolslide = inf;
1493 	else
1494 		inf = a->s3mvolslide;
1495 
1496 	if (tick) {
1497 		lo=inf&0xf;
1498 		hi=inf>>4;
1499 
1500 		if (!hi) {
1501 			a->tmpvolume-=lo;
1502 			if (a->tmpvolume<0) a->tmpvolume=0;
1503 		} else {
1504 			a->tmpvolume+=hi;
1505 			if (a->tmpvolume>64) a->tmpvolume=64;
1506 		}
1507 	}
1508 
1509 	return 0;
1510 }
1511 
DoXMEffect6(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1512 static int DoXMEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1513 {
1514 	if (a->main.period)
1515 		DoVibrato(tick, a);
1516 
1517 	return DoXMEffectA(tick, flags, a, mod, channel);
1518 }
1519 
DoXMEffectE1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1520 static int DoXMEffectE1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1521 {
1522 	UBYTE dat;
1523 
1524 	(void)flags; /* unused arg */
1525 	(void)mod; /* unused arg */
1526 	(void)channel; /* unused arg */
1527 
1528 	dat=UniGetByte();
1529 	if (!tick) {
1530 		if (dat) a->fportupspd=dat;
1531 		if (a->main.period)
1532 			a->tmpperiod-=(a->fportupspd<<2);
1533 	}
1534 
1535 	return 0;
1536 }
1537 
DoXMEffectE2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1538 static int DoXMEffectE2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1539 {
1540 	UBYTE dat;
1541 
1542 	(void)flags; /* unused arg */
1543 	(void)mod; /* unused arg */
1544 	(void)channel; /* unused arg */
1545 
1546 	dat=UniGetByte();
1547 	if (!tick) {
1548 		if (dat) a->fportdnspd=dat;
1549 		if (a->main.period)
1550 			a->tmpperiod+=(a->fportdnspd<<2);
1551 	}
1552 
1553 	return 0;
1554 }
1555 
DoXMEffectEA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1556 static int DoXMEffectEA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1557 {
1558 	UBYTE dat;
1559 
1560 	(void)flags; /* unused arg */
1561 	(void)mod; /* unused arg */
1562 	(void)channel; /* unused arg */
1563 
1564 	dat=UniGetByte();
1565 	if (!tick)
1566 		if (dat) a->fslideupspd=dat;
1567 	a->tmpvolume+=a->fslideupspd;
1568 	if (a->tmpvolume>64) a->tmpvolume=64;
1569 
1570 	return 0;
1571 }
1572 
DoXMEffectEB(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1573 static int DoXMEffectEB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1574 {
1575 	UBYTE dat;
1576 
1577 	(void)flags; /* unused arg */
1578 	(void)mod; /* unused arg */
1579 	(void)channel; /* unused arg */
1580 
1581 	dat=UniGetByte();
1582 	if (!tick)
1583 		if (dat) a->fslidednspd=dat;
1584 	a->tmpvolume-=a->fslidednspd;
1585 	if (a->tmpvolume<0) a->tmpvolume=0;
1586 
1587 	return 0;
1588 }
1589 
DoXMEffectG(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1590 static int DoXMEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1591 {
1592 	(void)tick; /* unused arg */
1593 	(void)flags; /* unused arg */
1594 	(void)a; /* unused arg */
1595 	(void)channel; /* unused arg */
1596 
1597 	mod->volume=UniGetByte()<<1;
1598 	if (mod->volume>128) mod->volume=128;
1599 
1600 	return 0;
1601 }
1602 
DoXMEffectH(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1603 static int DoXMEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1604 {
1605 	UBYTE inf;
1606 
1607 	(void)flags; /* unused arg */
1608 	(void)a; /* unused arg */
1609 	(void)channel; /* unused arg */
1610 
1611 	inf = UniGetByte();
1612 
1613 	if (tick) {
1614 		if (inf) mod->globalslide=inf;
1615 		else inf=mod->globalslide;
1616 		if (inf & 0xf0) inf&=0xf0;
1617 		mod->volume=mod->volume+((inf>>4)-(inf&0xf))*2;
1618 
1619 		if (mod->volume<0)
1620 			mod->volume=0;
1621 		else if (mod->volume>128)
1622 			mod->volume=128;
1623 	}
1624 
1625 	return 0;
1626 }
1627 
DoXMEffectL(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1628 static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1629 {
1630 	UBYTE dat;
1631 
1632 	(void)flags; /* unused arg */
1633 	(void)mod; /* unused arg */
1634 	(void)channel; /* unused arg */
1635 
1636 	dat=UniGetByte();
1637 	if ((!tick)&&(a->main.i)) {
1638 		UWORD points;
1639 		INSTRUMENT *i=a->main.i;
1640 		MP_VOICE *aout;
1641 
1642 		if ((aout=a->slave)) {
1643 			if (aout->venv.env) {
1644 				points=i->volenv[i->volpts-1].pos;
1645 				aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos;
1646 			}
1647 			if (aout->penv.env) {
1648 				points=i->panenv[i->panpts-1].pos;
1649 				aout->penv.p=aout->penv.env[(dat>points)?points:dat].pos;
1650 			}
1651 		}
1652 	}
1653 
1654 	return 0;
1655 }
1656 
DoXMEffectP(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1657 static int DoXMEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1658 {
1659 	UBYTE inf, lo, hi;
1660 	SWORD pan;
1661 
1662 	(void)flags; /* unused arg */
1663 	(void)channel; /* unused arg */
1664 
1665 	inf = UniGetByte();
1666 	if (!mod->panflag)
1667 		return 0;
1668 
1669 	if (inf)
1670 		a->pansspd = inf;
1671 	else
1672 		inf =a->pansspd;
1673 
1674 	if (tick) {
1675 		lo=inf&0xf;
1676 		hi=inf>>4;
1677 
1678 		/* slide right has absolute priority */
1679 		if (hi)
1680 			lo = 0;
1681 
1682 		pan=((a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning)+hi-lo;
1683 		a->main.panning=(pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1684 	}
1685 
1686 	return 0;
1687 }
1688 
DoXMEffectX1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1689 static int DoXMEffectX1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1690 {
1691 	UBYTE dat;
1692 
1693 	(void)flags; /* unused arg */
1694 	(void)mod; /* unused arg */
1695 	(void)channel; /* unused arg */
1696 
1697 	dat = UniGetByte();
1698 	if (dat)
1699 		a->ffportupspd = dat;
1700 	else
1701 		dat = a->ffportupspd;
1702 
1703 	if (a->main.period)
1704 		if (!tick) {
1705 			a->main.period-=dat;
1706 			a->tmpperiod-=dat;
1707 			a->ownper = 1;
1708 		}
1709 
1710 	return 0;
1711 }
1712 
DoXMEffectX2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1713 static int DoXMEffectX2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1714 {
1715 	UBYTE dat;
1716 
1717 	(void)flags; /* unused arg */
1718 	(void)mod; /* unused arg */
1719 	(void)channel; /* unused arg */
1720 
1721 	dat = UniGetByte();
1722 	if (dat)
1723 		a->ffportdnspd=dat;
1724 	else
1725 		dat = a->ffportdnspd;
1726 
1727 	if (a->main.period)
1728 		if (!tick) {
1729 			a->main.period+=dat;
1730 			a->tmpperiod+=dat;
1731 			a->ownper = 1;
1732 		}
1733 
1734 	return 0;
1735 }
1736 
1737 /*========== Impulse Tracker effects */
1738 
DoITToneSlide(UWORD tick,MP_CONTROL * a,UBYTE dat)1739 static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat)
1740 {
1741 	if (dat)
1742 		a->portspeed = dat;
1743 
1744 	/* if we don't come from another note, ignore the slide and play the note
1745 	   as is */
1746 	if (!a->oldnote || !a->main.period)
1747 			return;
1748 
1749 	if ((!tick)&&(a->newsamp)){
1750 		a->main.kick=KICK_NOTE;
1751 		a->main.start=-1;
1752 	} else
1753 		a->main.kick=(a->main.kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1754 
1755 	if (tick) {
1756 		int dist;
1757 
1758 		/* We have to slide a->main.period towards a->wantedperiod, compute the
1759 		   difference between those two values */
1760 		dist=a->main.period-a->wantedperiod;
1761 
1762 	    /* if they are equal or if portamentospeed is too big... */
1763 		if ((!dist)||((a->portspeed<<2)>abs(dist)))
1764 			/* ... make tmpperiod equal tperiod */
1765 			a->tmpperiod=a->main.period=a->wantedperiod;
1766 		else
1767 		  if (dist>0) {
1768 			a->tmpperiod-=a->portspeed<<2;
1769 			a->main.period-=a->portspeed<<2; /* dist>0 slide up */
1770 		} else {
1771 			a->tmpperiod+=a->portspeed<<2;
1772 			a->main.period+=a->portspeed<<2; /* dist<0 slide down */
1773 		}
1774 	} else
1775 		a->tmpperiod=a->main.period;
1776 	a->ownper=1;
1777 }
1778 
DoITEffectG(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1779 static int DoITEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1780 {
1781 	(void)flags; /* unused arg */
1782 	(void)mod; /* unused arg */
1783 	(void)channel; /* unused arg */
1784 
1785 	DoITToneSlide(tick, a, UniGetByte());
1786 
1787 	return 0;
1788 }
1789 
DoITVibrato(UWORD tick,MP_CONTROL * a,UBYTE dat)1790 static void DoITVibrato(UWORD tick, MP_CONTROL *a, UBYTE dat)
1791 {
1792 	UBYTE q;
1793 	UWORD temp=0;
1794 
1795 	if (!tick) {
1796 		if (dat&0x0f) a->vibdepth=dat&0xf;
1797 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1798 	}
1799 	if (!a->main.period)
1800 			return;
1801 
1802 	q=(a->vibpos>>2)&0x1f;
1803 
1804 	switch (a->wavecontrol&3) {
1805 	case 0: /* sine */
1806 		temp=VibratoTable[q];
1807 		break;
1808 	case 1: /* square wave */
1809 		temp=255;
1810 		break;
1811 	case 2: /* ramp down */
1812 		q<<=3;
1813 		if (a->vibpos<0) q=255-q;
1814 		temp=q;
1815 		break;
1816 	case 3: /* random */
1817 		temp=getrandom(256);
1818 		break;
1819 	}
1820 
1821 	temp*=a->vibdepth;
1822 	temp>>=8;
1823 	temp<<=2;
1824 
1825 	if (a->vibpos>=0)
1826 		a->main.period=a->tmpperiod+temp;
1827 	else
1828 		a->main.period=a->tmpperiod-temp;
1829 	a->ownper=1;
1830 
1831 	a->vibpos+=a->vibspd;
1832 }
1833 
DoITEffectH(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1834 static int DoITEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1835 {
1836 	(void)flags; /* unused arg */
1837 	(void)mod; /* unused arg */
1838 	(void)channel; /* unused arg */
1839 
1840 	DoITVibrato(tick, a, UniGetByte());
1841 
1842 	return 0;
1843 }
1844 
DoITEffectI(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1845 static int DoITEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1846 {
1847 	UBYTE inf, on, off;
1848 
1849 	(void)tick; /* unused arg */
1850 	(void)flags; /* unused arg */
1851 	(void)mod; /* unused arg */
1852 	(void)channel; /* unused arg */
1853 
1854 	inf = UniGetByte();
1855 	if (inf)
1856 		a->s3mtronof = inf;
1857 	else {
1858 		inf = a->s3mtronof;
1859 		if (!inf)
1860 			return 0;
1861 	}
1862 
1863 	on=(inf>>4);
1864 	off=(inf&0xf);
1865 
1866 	a->s3mtremor%=(on+off);
1867 	a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1868 	a->ownvol = 1;
1869 	a->s3mtremor++;
1870 
1871 	return 0;
1872 }
1873 
DoITEffectM(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1874 static int DoITEffectM(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1875 {
1876 	(void)tick; /* unused arg */
1877 	(void)flags; /* unused arg */
1878 	(void)mod; /* unused arg */
1879 	(void)channel; /* unused arg */
1880 
1881 	a->main.chanvol=UniGetByte();
1882 	if (a->main.chanvol>64)
1883 		a->main.chanvol=64;
1884 	else if (a->main.chanvol<0)
1885 		a->main.chanvol=0;
1886 
1887 	return 0;
1888 }
1889 
DoITEffectN(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1890 static int DoITEffectN(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1891 {
1892 	UBYTE inf, lo, hi;
1893 
1894 	(void)flags; /* unused arg */
1895 	(void)mod; /* unused arg */
1896 	(void)channel; /* unused arg */
1897 
1898 	inf = UniGetByte();
1899 
1900 	if (inf)
1901 		a->chanvolslide = inf;
1902 	else
1903 		inf = a->chanvolslide;
1904 
1905 	lo=inf&0xf;
1906 	hi=inf>>4;
1907 
1908 	if (!hi)
1909 		a->main.chanvol-=lo;
1910 	else
1911 	  if (!lo) {
1912 		a->main.chanvol+=hi;
1913 	} else
1914 	  if (hi==0xf) {
1915 		if (!tick) a->main.chanvol-=lo;
1916 	} else
1917 	  if (lo==0xf) {
1918 		if (!tick) a->main.chanvol+=hi;
1919 	}
1920 
1921 	if (a->main.chanvol<0)
1922 		a->main.chanvol=0;
1923 	else if (a->main.chanvol>64)
1924 		a->main.chanvol=64;
1925 
1926 	return 0;
1927 }
1928 
DoITEffectP(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1929 static int DoITEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1930 {
1931 	UBYTE inf, lo, hi;
1932 	SWORD pan;
1933 
1934 	(void)flags; /* unused arg */
1935 	(void)channel; /* unused arg */
1936 
1937 	inf = UniGetByte();
1938 	if (inf)
1939 		a->pansspd = inf;
1940 	else
1941 		inf = a->pansspd;
1942 
1943 	if (!mod->panflag)
1944 		return 0;
1945 
1946 	lo=inf&0xf;
1947 	hi=inf>>4;
1948 
1949 	pan=(a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning;
1950 
1951 	if (!hi)
1952 		pan+=lo<<2;
1953 	else
1954 	  if (!lo) {
1955 		pan-=hi<<2;
1956 	} else
1957 	  if (hi==0xf) {
1958 		if (!tick) pan+=lo<<2;
1959 	} else
1960 	  if (lo==0xf) {
1961 		if (!tick) pan-=hi<<2;
1962 	}
1963 	a->main.panning=
1964 	  (pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1965 
1966 	return 0;
1967 }
1968 
DoITEffectT(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1969 static int DoITEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1970 {
1971 	UBYTE tempo;
1972 	SWORD temp;
1973 
1974 	(void)tick; /* unused arg */
1975 	(void)flags; /* unused arg */
1976 	(void)a; /* unused arg */
1977 	(void)channel; /* unused arg */
1978 
1979    	tempo = UniGetByte();
1980 
1981 	if (mod->patdly2)
1982 		return 0;
1983 
1984 	temp = mod->bpm;
1985 	if (tempo & 0x10)
1986 		temp += (tempo & 0x0f);
1987 	else
1988 		temp -= tempo;
1989 
1990 	mod->bpm=(temp>255)?255:(temp<1?1:temp);
1991 
1992 	return 0;
1993 }
1994 
DoITEffectU(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1995 static int DoITEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1996 {
1997 	UBYTE dat, q;
1998 	UWORD temp = 0;	/* silence warning */
1999 
2000 	(void)flags; /* unused arg */
2001 	(void)mod; /* unused arg */
2002 	(void)channel; /* unused arg */
2003 
2004 	dat = UniGetByte();
2005 	if (!tick) {
2006 		if (dat&0x0f) a->vibdepth=dat&0xf;
2007 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
2008 	}
2009 	if (a->main.period) {
2010 		q=(a->vibpos>>2)&0x1f;
2011 
2012 		switch (a->wavecontrol&3) {
2013 		case 0: /* sine */
2014 			temp=VibratoTable[q];
2015 			break;
2016 		case 1: /* square wave */
2017 			temp=255;
2018 			break;
2019 		case 2: /* ramp down */
2020 			q<<=3;
2021 			if (a->vibpos<0) q=255-q;
2022 			temp=q;
2023 			break;
2024 		case 3: /* random */
2025 			temp=getrandom(256);
2026 			break;
2027 		}
2028 
2029 		temp*=a->vibdepth;
2030 		temp>>=8;
2031 
2032 		if (a->vibpos>=0)
2033 			a->main.period=a->tmpperiod+temp;
2034 		else
2035 			a->main.period=a->tmpperiod-temp;
2036 		a->ownper = 1;
2037 
2038 		a->vibpos+=a->vibspd;
2039 	}
2040 
2041 	return 0;
2042 }
2043 
DoITEffectW(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2044 static int DoITEffectW(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2045 {
2046 	UBYTE inf, lo, hi;
2047 
2048 	(void)flags; /* unused arg */
2049 	(void)a; /* unused arg */
2050 	(void)channel; /* unused arg */
2051 
2052 	inf = UniGetByte();
2053 
2054 	if (inf)
2055 		mod->globalslide = inf;
2056 	else
2057 		inf = mod->globalslide;
2058 
2059 	lo=inf&0xf;
2060 	hi=inf>>4;
2061 
2062 	if (!lo) {
2063 		if (tick) mod->volume+=hi;
2064 	} else
2065 	  if (!hi) {
2066 		if (tick) mod->volume-=lo;
2067 	} else
2068 	  if (lo==0xf) {
2069 		if (!tick) mod->volume+=hi;
2070 	} else
2071 	  if (hi==0xf) {
2072 		if (!tick) mod->volume-=lo;
2073 	}
2074 
2075 	if (mod->volume<0)
2076 		mod->volume=0;
2077 	else if (mod->volume>128)
2078 		mod->volume=128;
2079 
2080 	return 0;
2081 }
2082 
DoITEffectY(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2083 static int DoITEffectY(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2084 {
2085 	UBYTE dat, q;
2086 	SLONG temp = 0;	/* silence warning */
2087 
2088 	(void)flags; /* unused arg */
2089 
2090 	dat=UniGetByte();
2091 	if (!tick) {
2092 		if (dat&0x0f) a->panbdepth=(dat&0xf);
2093 		if (dat&0xf0) a->panbspd=(dat&0xf0)>>4;
2094 	}
2095 	if (mod->panflag) {
2096 		q=a->panbpos;
2097 
2098 		switch (a->panbwave) {
2099 		case 0: /* sine */
2100 			temp=PanbrelloTable[q];
2101 			break;
2102 		case 1: /* square wave */
2103 			temp=(q<0x80)?64:0;
2104 			break;
2105 		case 2: /* ramp down */
2106 			q<<=3;
2107 			temp=q;
2108 			break;
2109 		case 3: /* random */
2110 			temp=getrandom(256);
2111 			break;
2112 		}
2113 
2114 		temp*=a->panbdepth;
2115 		temp=(temp/8)+mod->panning[channel];
2116 
2117 		a->main.panning=
2118 			(temp<PAN_LEFT)?PAN_LEFT:(temp>PAN_RIGHT?PAN_RIGHT:temp);
2119 		a->panbpos+=a->panbspd;
2120 
2121 	}
2122 
2123 	return 0;
2124 }
2125 
2126 static void DoNNAEffects(MODULE *, MP_CONTROL *, UBYTE);
2127 
2128 /* Impulse/Scream Tracker Sxx effects.
2129    All Sxx effects share the same memory space. */
DoITEffectS0(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2130 static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2131 {
2132 	UBYTE dat, inf, c;
2133 
2134 	dat = UniGetByte();
2135 	inf=dat&0xf;
2136 	c=dat>>4;
2137 
2138 	if (!dat) {
2139 		c=a->sseffect;
2140 		inf=a->ssdata;
2141 	} else {
2142 		a->sseffect=c;
2143 		a->ssdata=inf;
2144 	}
2145 
2146 	switch (c) {
2147 	case SS_GLISSANDO: /* S1x set glissando voice */
2148 		DoEEffects(tick, flags, a, mod, channel, 0x30|inf);
2149 		break;
2150 	case SS_FINETUNE: /* S2x set finetune */
2151 		DoEEffects(tick, flags, a, mod, channel, 0x50|inf);
2152 		break;
2153 	case SS_VIBWAVE: /* S3x set vibrato waveform */
2154 		DoEEffects(tick, flags, a, mod, channel, 0x40|inf);
2155 		break;
2156 	case SS_TREMWAVE: /* S4x set tremolo waveform */
2157 		DoEEffects(tick, flags, a, mod, channel, 0x70|inf);
2158 		break;
2159 	case SS_PANWAVE: /* S5x panbrello */
2160 		a->panbwave=inf;
2161 		break;
2162 	case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */
2163 		DoEEffects(tick, flags, a, mod, channel, 0xe0|inf);
2164 		break;
2165 	case SS_S7EFFECTS: /* S7x instrument / NNA commands */
2166 		DoNNAEffects(mod, a, inf);
2167 		break;
2168 	case SS_PANNING: /* S8x set panning position */
2169 		DoEEffects(tick, flags, a, mod, channel, 0x80 | inf);
2170 		break;
2171 	case SS_SURROUND: /* S9x set surround sound */
2172 		if (mod->panflag)
2173 			a->main.panning = mod->panning[channel] = PAN_SURROUND;
2174 		break;
2175 	case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
2176 		if (!tick) {
2177 			a->hioffset=inf<<16;
2178 			a->main.start=a->hioffset|a->soffset;
2179 
2180 			if ((a->main.s)&&(a->main.start>a->main.s->length))
2181 				a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2182 				    a->main.s->loopstart:a->main.s->length;
2183 		}
2184 		break;
2185 	case SS_PATLOOP: /* SBx pattern loop */
2186 		DoEEffects(tick, flags, a, mod, channel, 0x60|inf);
2187 		break;
2188 	case SS_NOTECUT: /* SCx notecut */
2189 		if (!inf) inf = 1;
2190 		DoEEffects(tick, flags, a, mod, channel, 0xC0|inf);
2191 		break;
2192 	case SS_NOTEDELAY: /* SDx notedelay */
2193 		DoEEffects(tick, flags, a, mod, channel, 0xD0|inf);
2194 		break;
2195 	case SS_PATDELAY: /* SEx patterndelay */
2196 		DoEEffects(tick, flags, a, mod, channel, 0xE0|inf);
2197 		break;
2198 	}
2199 
2200 	return 0;
2201 }
2202 
2203 /*========== Impulse Tracker Volume/Pan Column effects */
2204 
2205 /*
2206  * All volume/pan column effects share the same memory space.
2207  */
2208 
DoVolEffects(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2209 static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2210 {
2211 	UBYTE c, inf;
2212 
2213 	(void)channel; /* unused arg */
2214 
2215 	c = UniGetByte();
2216 	inf = UniGetByte();
2217 
2218 	if ((!c)&&(!inf)) {
2219 		c=a->voleffect;
2220 		inf=a->voldata;
2221 	} else {
2222 		a->voleffect=c;
2223 		a->voldata=inf;
2224 	}
2225 
2226 	if (c)
2227 		switch (c) {
2228 		case VOL_VOLUME:
2229 			if (tick) break;
2230 			if (inf>64) inf=64;
2231 			a->tmpvolume=inf;
2232 			break;
2233 		case VOL_PANNING:
2234 			if (mod->panflag)
2235 				a->main.panning=inf;
2236 			break;
2237 		case VOL_VOLSLIDE:
2238 			DoS3MVolSlide(tick, flags, a, inf);
2239 			return 1;
2240 		case VOL_PITCHSLIDEDN:
2241 			if (a->main.period)
2242 				DoS3MSlideDn(tick, a, inf);
2243 			break;
2244 		case VOL_PITCHSLIDEUP:
2245 			if (a->main.period)
2246 				DoS3MSlideUp(tick, a, inf);
2247 			break;
2248 		case VOL_PORTAMENTO:
2249 			DoITToneSlide(tick, a, inf);
2250 			break;
2251 		case VOL_VIBRATO:
2252 			DoITVibrato(tick, a, inf);
2253 			break;
2254 	}
2255 
2256 	return 0;
2257 }
2258 
2259 /*========== UltraTracker effects */
2260 
DoULTEffect9(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2261 static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2262 {
2263 	UWORD offset=UniGetWord();
2264 
2265 	(void)tick; /* unused arg */
2266 	(void)flags; /* unused arg */
2267 	(void)mod; /* unused arg */
2268 	(void)channel; /* unused arg */
2269 
2270 	if (offset)
2271 		a->ultoffset=offset;
2272 
2273 	a->main.start=a->ultoffset<<2;
2274 	if ((a->main.s)&&(a->main.start>a->main.s->length))
2275 		a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2276 		    a->main.s->loopstart:a->main.s->length;
2277 
2278 	return 0;
2279 }
2280 
2281 /*========== OctaMED effects */
2282 
DoMEDSpeed(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2283 static int DoMEDSpeed(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2284 {
2285 	UWORD speed=UniGetWord();
2286 
2287 	(void)tick; /* unused arg */
2288 	(void)flags; /* unused arg */
2289 	(void)a; /* unused arg */
2290 	(void)channel; /* unused arg */
2291 
2292 	mod->bpm=speed;
2293 
2294 	return 0;
2295 }
2296 
DoMEDEffectF1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2297 static int DoMEDEffectF1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2298 {
2299 	DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/2));
2300 
2301 	return 0;
2302 }
2303 
DoMEDEffectF2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2304 static int DoMEDEffectF2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2305 {
2306 	DoEEffects(tick, flags, a, mod, channel, 0xd0|(mod->sngspd/2));
2307 
2308 	return 0;
2309 }
2310 
DoMEDEffectF3(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2311 static int DoMEDEffectF3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2312 {
2313 	DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/3));
2314 
2315 	return 0;
2316 }
2317 
2318 /*========== Oktalyzer effects */
2319 
DoOktArp(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2320 static int DoOktArp(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2321 {
2322 	UBYTE dat, dat2;
2323 
2324 	(void)mod; /* unused arg */
2325 	(void)channel; /* unused arg */
2326 
2327 	dat2 = UniGetByte();	/* arpeggio style */
2328 	dat = UniGetByte();
2329 	if (!tick) {
2330 		if (!dat && (flags & UF_ARPMEM))
2331 			dat=a->arpmem;
2332 		else
2333 			a->arpmem=dat;
2334 	}
2335 	if (a->main.period)
2336 		DoArpeggio(tick, flags, a, dat2);
2337 
2338 	return 0;
2339 }
2340 
2341 /*========== General player functions */
2342 
DoNothing(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2343 static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2344 {
2345 	(void)tick; /* unused arg */
2346 	(void)flags; /* unused arg */
2347 	(void)a; /* unused arg */
2348 	(void)mod; /* unused arg */
2349 	(void)channel; /* unused arg */
2350 
2351 	UniSkipOpcode();
2352 
2353 	return 0;
2354 }
2355 
2356 typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD);
2357 
2358 static effect_func effects[UNI_LAST] = {
2359 		DoNothing,		/* 0 */
2360 		DoNothing,		/* UNI_NOTE */
2361 		DoNothing,		/* UNI_INSTRUMENT */
2362 		DoPTEffect0,	/* UNI_PTEFFECT0 */
2363 		DoPTEffect1,	/* UNI_PTEFFECT1 */
2364 		DoPTEffect2,	/* UNI_PTEFFECT2 */
2365 		DoPTEffect3,	/* UNI_PTEFFECT3 */
2366 		DoPTEffect4,	/* UNI_PTEFFECT4 */
2367 		DoPTEffect5,	/* UNI_PTEFFECT5 */
2368 		DoPTEffect6,	/* UNI_PTEFFECT6 */
2369 		DoPTEffect7,	/* UNI_PTEFFECT7 */
2370 		DoPTEffect8,	/* UNI_PTEFFECT8 */
2371 		DoPTEffect9,	/* UNI_PTEFFECT9 */
2372 		DoPTEffectA,	/* UNI_PTEFFECTA */
2373 		DoPTEffectB,	/* UNI_PTEFFECTB */
2374 		DoPTEffectC,	/* UNI_PTEFFECTC */
2375 		DoPTEffectD,	/* UNI_PTEFFECTD */
2376 		DoPTEffectE,	/* UNI_PTEFFECTE */
2377 		DoPTEffectF,	/* UNI_PTEFFECTF */
2378 		DoS3MEffectA,	/* UNI_S3MEFFECTA */
2379 		DoS3MEffectD,	/* UNI_S3MEFFECTD */
2380 		DoS3MEffectE,	/* UNI_S3MEFFECTE */
2381 		DoS3MEffectF,	/* UNI_S3MEFFECTF */
2382 		DoS3MEffectI,	/* UNI_S3MEFFECTI */
2383 		DoS3MEffectQ,	/* UNI_S3MEFFECTQ */
2384 		DoS3MEffectR,	/* UNI_S3MEFFECTR */
2385 		DoS3MEffectT,	/* UNI_S3MEFFECTT */
2386 		DoS3MEffectU,	/* UNI_S3MEFFECTU */
2387 		DoKeyOff,		/* UNI_KEYOFF */
2388 		DoKeyFade,		/* UNI_KEYFADE */
2389 		DoVolEffects,	/* UNI_VOLEFFECTS */
2390 		DoPTEffect4,	/* UNI_XMEFFECT4 */
2391 		DoXMEffect6,	/* UNI_XMEFFECT6 */
2392 		DoXMEffectA,	/* UNI_XMEFFECTA */
2393 		DoXMEffectE1,	/* UNI_XMEFFECTE1 */
2394 		DoXMEffectE2,	/* UNI_XMEFFECTE2 */
2395 		DoXMEffectEA,	/* UNI_XMEFFECTEA */
2396 		DoXMEffectEB,	/* UNI_XMEFFECTEB */
2397 		DoXMEffectG,	/* UNI_XMEFFECTG */
2398 		DoXMEffectH,	/* UNI_XMEFFECTH */
2399 		DoXMEffectL,	/* UNI_XMEFFECTL */
2400 		DoXMEffectP,	/* UNI_XMEFFECTP */
2401 		DoXMEffectX1,	/* UNI_XMEFFECTX1 */
2402 		DoXMEffectX2,	/* UNI_XMEFFECTX2 */
2403 		DoITEffectG,	/* UNI_ITEFFECTG */
2404 		DoITEffectH,	/* UNI_ITEFFECTH */
2405 		DoITEffectI,	/* UNI_ITEFFECTI */
2406 		DoITEffectM,	/* UNI_ITEFFECTM */
2407 		DoITEffectN,	/* UNI_ITEFFECTN */
2408 		DoITEffectP,	/* UNI_ITEFFECTP */
2409 		DoITEffectT,	/* UNI_ITEFFECTT */
2410 		DoITEffectU,	/* UNI_ITEFFECTU */
2411 		DoITEffectW,	/* UNI_ITEFFECTW */
2412 		DoITEffectY,	/* UNI_ITEFFECTY */
2413 		DoNothing,		/* UNI_ITEFFECTZ */
2414 		DoITEffectS0,	/* UNI_ITEFFECTS0 */
2415 		DoULTEffect9,	/* UNI_ULTEFFECT9 */
2416 		DoMEDSpeed,		/* UNI_MEDSPEED */
2417 		DoMEDEffectF1,	/* UNI_MEDEFFECTF1 */
2418 		DoMEDEffectF2,	/* UNI_MEDEFFECTF2 */
2419 		DoMEDEffectF3,	/* UNI_MEDEFFECTF3 */
2420 		DoOktArp,		/* UNI_OKTARP */
2421 };
2422 
pt_playeffects(MODULE * mod,SWORD channel,MP_CONTROL * a)2423 static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
2424 {
2425 	UWORD tick = mod->vbtick;
2426 	UWORD flags = mod->flags;
2427 	UBYTE c;
2428 	int explicitslides = 0;
2429 	effect_func f;
2430 
2431 	while((c=UniGetByte())) {
2432 		f = effects[c];
2433 		if (f != DoNothing)
2434 				a->sliding = 0;
2435 		explicitslides |= f(tick, flags, a, mod, channel);
2436 	}
2437 	return explicitslides;
2438 }
2439 
DoNNAEffects(MODULE * mod,MP_CONTROL * a,UBYTE dat)2440 static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2441 {
2442 	int t;
2443 	MP_VOICE *aout;
2444 
2445 	dat&=0xf;
2446 	aout=(a->slave)?a->slave:NULL;
2447 
2448 	switch (dat) {
2449 	case 0x0: /* past note cut */
2450 		for (t=0;t<md_sngchn;t++)
2451 			if (mod->voice[t].master==a)
2452 				mod->voice[t].main.fadevol=0;
2453 		break;
2454 	case 0x1: /* past note off */
2455 		for (t=0;t<md_sngchn;t++)
2456 			if (mod->voice[t].master==a) {
2457 				mod->voice[t].main.keyoff|=KEY_OFF;
2458 				if ((!(mod->voice[t].venv.flg & EF_ON))||
2459 				   (mod->voice[t].venv.flg & EF_LOOP))
2460 					mod->voice[t].main.keyoff=KEY_KILL;
2461 			}
2462 		break;
2463 	case 0x2: /* past note fade */
2464 		for (t=0;t<md_sngchn;t++)
2465 			if (mod->voice[t].master==a)
2466 				mod->voice[t].main.keyoff|=KEY_FADE;
2467 		break;
2468 	case 0x3: /* set NNA note cut */
2469 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CUT;
2470 		break;
2471 	case 0x4: /* set NNA note continue */
2472 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CONTINUE;
2473 		break;
2474 	case 0x5: /* set NNA note off */
2475 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF;
2476 		break;
2477 	case 0x6: /* set NNA note fade */
2478 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE;
2479 		break;
2480 	case 0x7: /* disable volume envelope */
2481 		if (aout)
2482 			aout->main.volflg&=~EF_ON;
2483 		break;
2484 	case 0x8: /* enable volume envelope  */
2485 		if (aout)
2486 			aout->main.volflg|=EF_ON;
2487 		break;
2488 	case 0x9: /* disable panning envelope */
2489 		if (aout)
2490 			aout->main.panflg&=~EF_ON;
2491 		break;
2492 	case 0xa: /* enable panning envelope */
2493 		if (aout)
2494 			aout->main.panflg|=EF_ON;
2495 		break;
2496 	case 0xb: /* disable pitch envelope */
2497 		if (aout)
2498 			aout->main.pitflg&=~EF_ON;
2499 		break;
2500 	case 0xc: /* enable pitch envelope */
2501 		if (aout)
2502 			aout->main.pitflg|=EF_ON;
2503 		break;
2504 	}
2505 }
2506 
pt_UpdateVoices(MODULE * mod,int max_volume)2507 void pt_UpdateVoices(MODULE *mod, int max_volume)
2508 {
2509 	SWORD envpan,envvol,envpit,channel;
2510 	UWORD playperiod;
2511 	SLONG vibval,vibdpt;
2512 	ULONG tmpvol;
2513 
2514 	MP_VOICE *aout;
2515 	INSTRUMENT *i;
2516 	SAMPLE *s;
2517 
2518 	mod->totalchn=mod->realchn=0;
2519 	for (channel=0;channel<md_sngchn;channel++) {
2520 		aout=&mod->voice[channel];
2521 		i=aout->main.i;
2522 		s=aout->main.s;
2523 
2524 		if (!s || !s->length) continue;
2525 
2526 		if (aout->main.period<40)
2527 			aout->main.period=40;
2528 		else if (aout->main.period>50000)
2529 			aout->main.period=50000;
2530 
2531 		if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) {
2532 			Voice_Play_internal(channel,s,(aout->main.start==-1)?
2533 			    ((s->flags&SF_UST_LOOP)?s->loopstart:0):aout->main.start);
2534 			aout->main.fadevol=32768;
2535 			aout->aswppos=0;
2536 		}
2537 
2538 		envvol = 256;
2539 		envpan = PAN_CENTER;
2540 		envpit = 32;
2541 		if (i && ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_ENV))) {
2542 			if (aout->main.volflg & EF_ON)
2543 				envvol = StartEnvelope(&aout->venv,aout->main.volflg,
2544 				  i->volpts,i->volsusbeg,i->volsusend,
2545 				  i->volbeg,i->volend,i->volenv,aout->main.keyoff);
2546 			if (aout->main.panflg & EF_ON)
2547 				envpan = StartEnvelope(&aout->penv,aout->main.panflg,
2548 				  i->panpts,i->pansusbeg,i->pansusend,
2549 				  i->panbeg,i->panend,i->panenv,aout->main.keyoff);
2550 			if (aout->main.pitflg & EF_ON)
2551 				envpit = StartEnvelope(&aout->cenv,aout->main.pitflg,
2552 				  i->pitpts,i->pitsusbeg,i->pitsusend,
2553 				  i->pitbeg,i->pitend,i->pitenv,aout->main.keyoff);
2554 
2555 			if (aout->cenv.flg & EF_ON)
2556 				aout->masterperiod=GetPeriod(mod->flags,
2557 				  (UWORD)aout->main.note<<1, aout->master->speed);
2558 		} else {
2559 			if (aout->main.volflg & EF_ON)
2560 				envvol = ProcessEnvelope(aout,&aout->venv,256);
2561 			if (aout->main.panflg & EF_ON)
2562 				envpan = ProcessEnvelope(aout,&aout->penv,PAN_CENTER);
2563 			if (aout->main.pitflg & EF_ON)
2564 				envpit = ProcessEnvelope(aout,&aout->cenv,32);
2565 		}
2566 		aout->main.kick=KICK_ABSENT;
2567 
2568 		tmpvol = aout->main.fadevol;	/* max 32768 */
2569 		tmpvol *= aout->main.chanvol;	/* * max 64 */
2570 		tmpvol *= aout->main.outvolume;	/* * max 256 */
2571 		tmpvol /= (256 * 64);			/* tmpvol is max 32768 again */
2572 		aout->totalvol = tmpvol >> 2;	/* used to determine samplevolume */
2573 		tmpvol *= envvol;				/* * max 256 */
2574 		tmpvol *= mod->volume;			/* * max 128 */
2575 		tmpvol /= (128 * 256 * 128);
2576 
2577 		/* fade out */
2578 		if (mod->sngpos>=mod->numpos)
2579 			tmpvol=0;
2580 		else
2581 			tmpvol=(tmpvol*max_volume)/128;
2582 
2583 		if ((aout->masterchn!=-1)&& mod->control[aout->masterchn].muted)
2584 			Voice_SetVolume_internal(channel,0);
2585 		else {
2586 			Voice_SetVolume_internal(channel,tmpvol);
2587 			if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2588 				mod->realchn++;
2589 			mod->totalchn++;
2590 		}
2591 
2592 		if (aout->main.panning==PAN_SURROUND)
2593 			Voice_SetPanning_internal(channel,PAN_SURROUND);
2594 		else
2595 			if ((mod->panflag)&&(aout->penv.flg & EF_ON))
2596 				Voice_SetPanning_internal(channel,
2597 				    DoPan(envpan,aout->main.panning));
2598 			else
2599 				Voice_SetPanning_internal(channel,aout->main.panning);
2600 
2601 		if (aout->main.period && s->vibdepth)
2602 			switch (s->vibtype) {
2603 			case 0:
2604 				vibval=avibtab[s->avibpos&127];
2605 				if (aout->avibpos & 0x80) vibval=-vibval;
2606 				break;
2607 			case 1:
2608 				vibval=64;
2609 				if (aout->avibpos & 0x80) vibval=-vibval;
2610 				break;
2611 			case 2:
2612 				vibval=63-(((aout->avibpos+128)&255)>>1);
2613 				break;
2614 			default:
2615 				vibval=(((aout->avibpos+128)&255)>>1)-64;
2616 				break;
2617 			}
2618 		else
2619 			vibval=0;
2620 
2621 		if (s->vibflags & AV_IT) {
2622 			if ((aout->aswppos>>8)<s->vibdepth) {
2623 				aout->aswppos += s->vibsweep;
2624 				vibdpt=aout->aswppos;
2625 			} else
2626 				vibdpt=s->vibdepth<<8;
2627 			vibval=(vibval*vibdpt)>>16;
2628 			if (aout->mflag) {
2629 				if (!(mod->flags&UF_LINEAR)) vibval>>=1;
2630 				aout->main.period-=vibval;
2631 			}
2632 		} else {
2633 			/* do XM style auto-vibrato */
2634 			if (!(aout->main.keyoff & KEY_OFF)) {
2635 				if (aout->aswppos<s->vibsweep) {
2636 					vibdpt=(aout->aswppos*s->vibdepth)/s->vibsweep;
2637 					aout->aswppos++;
2638 				} else
2639 					vibdpt=s->vibdepth;
2640 			} else {
2641 				/* keyoff -> depth becomes 0 if final depth wasn't reached or
2642 				   stays at final level if depth WAS reached */
2643 				if (aout->aswppos>=s->vibsweep)
2644 					vibdpt=s->vibdepth;
2645 				else
2646 					vibdpt=0;
2647 			}
2648 			vibval=(vibval*vibdpt)>>8;
2649 			aout->main.period-=vibval;
2650 		}
2651 
2652 		/* update vibrato position */
2653 		aout->avibpos=(aout->avibpos+s->vibrate)&0xff;
2654 
2655 		/* process pitch envelope */
2656 		playperiod=aout->main.period;
2657 
2658 		if ((aout->main.pitflg&EF_ON)&&(envpit!=32)) {
2659 			long p1;
2660 
2661 			envpit-=32;
2662 			if ((aout->main.note<<1)+envpit<=0) envpit=-(aout->main.note<<1);
2663 
2664 			p1=GetPeriod(mod->flags, ((UWORD)aout->main.note<<1)+envpit,
2665 			    aout->master->speed)-aout->masterperiod;
2666 			if (p1>0) {
2667 				if ((UWORD)(playperiod+p1)<=playperiod) {
2668 					p1=0;
2669 					aout->main.keyoff|=KEY_OFF;
2670 				}
2671 			} else if (p1<0) {
2672 				if ((UWORD)(playperiod+p1)>=playperiod) {
2673 					p1=0;
2674 					aout->main.keyoff|=KEY_OFF;
2675 				}
2676 			}
2677 			playperiod+=p1;
2678 		}
2679 
2680 		if (!aout->main.fadevol) { /* check for a dead note (fadevol=0) */
2681 			Voice_Stop_internal(channel);
2682 			mod->totalchn--;
2683 			if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2684 				mod->realchn--;
2685 		} else {
2686 			Voice_SetFrequency_internal(channel,
2687 			                            getfrequency(mod->flags,playperiod));
2688 
2689 			/* if keyfade, start substracting fadeoutspeed from fadevol: */
2690 			if ((i)&&(aout->main.keyoff&KEY_FADE)) {
2691 				if (aout->main.fadevol>=i->volfade)
2692 					aout->main.fadevol-=i->volfade;
2693 				else
2694 					aout->main.fadevol=0;
2695 			}
2696 		}
2697 
2698 		md_bpm=mod->bpm+mod->relspd;
2699 		if (md_bpm<32)
2700 			md_bpm=32;
2701 		else if ((!(mod->flags&UF_HIGHBPM)) && md_bpm>255)
2702 			md_bpm=255;
2703 	}
2704 }
2705 
2706 /* Handles new notes or instruments */
pt_Notes(MODULE * mod)2707 void pt_Notes(MODULE *mod)
2708 {
2709 	SWORD channel;
2710 	MP_CONTROL *a;
2711 	UBYTE c,inst;
2712 	int tr,funky; /* funky is set to indicate note or instrument change */
2713 
2714 	for (channel=0;channel<mod->numchn;channel++) {
2715 		a=&mod->control[channel];
2716 
2717 		if (mod->sngpos>=mod->numpos) {
2718 			tr=mod->numtrk;
2719 			mod->numrow=0;
2720 		} else {
2721 			tr=mod->patterns[(mod->positions[mod->sngpos]*mod->numchn)+channel];
2722 			mod->numrow=mod->pattrows[mod->positions[mod->sngpos]];
2723 		}
2724 
2725 		a->row=(tr<mod->numtrk)?UniFindRow(mod->tracks[tr],mod->patpos):NULL;
2726 		a->newsamp=0;
2727 		if (!mod->vbtick) a->main.notedelay=0;
2728 
2729 		if (!a->row) continue;
2730 		UniSetRow(a->row);
2731 		funky=0;
2732 
2733 		while((c=UniGetByte()))
2734 			switch (c) {
2735 			case UNI_NOTE:
2736 				funky|=1;
2737 				a->oldnote=a->anote,a->anote=UniGetByte();
2738 				a->main.kick =KICK_NOTE;
2739 				a->main.start=-1;
2740 				a->sliding=0;
2741 
2742 				/* retrig tremolo and vibrato waves ? */
2743 				if (!(a->wavecontrol & 0x80)) a->trmpos=0;
2744 				if (!(a->wavecontrol & 0x08)) a->vibpos=0;
2745 				if (!a->panbwave) a->panbpos=0;
2746 				break;
2747 			case UNI_INSTRUMENT:
2748 				inst=UniGetByte();
2749 				if (inst>=mod->numins) break; /* safety valve */
2750 				funky|=2;
2751 				a->main.i=(mod->flags & UF_INST)?&mod->instruments[inst]:NULL;
2752 				a->retrig=0;
2753 				a->s3mtremor=0;
2754 				a->ultoffset=0;
2755 				a->main.sample=inst;
2756 				break;
2757 			default:
2758 				UniSkipOpcode();
2759 				break;
2760 			}
2761 
2762 		if (funky) {
2763 			INSTRUMENT *i;
2764 			SAMPLE *s;
2765 
2766 			if ((i=a->main.i)) {
2767 				if (i->samplenumber[a->anote] >= mod->numsmp) continue;
2768 				s=&mod->samples[i->samplenumber[a->anote]];
2769 				a->main.note=i->samplenote[a->anote];
2770 			} else {
2771 				a->main.note=a->anote;
2772 				s=&mod->samples[a->main.sample];
2773 			}
2774 
2775 			if (a->main.s!=s) {
2776 				a->main.s=s;
2777 				a->newsamp=a->main.period;
2778 			}
2779 
2780 			/* channel or instrument determined panning ? */
2781 			a->main.panning=mod->panning[channel];
2782 			if (s->flags & SF_OWNPAN)
2783 				a->main.panning=s->panning;
2784 			else if ((i)&&(i->flags & IF_OWNPAN))
2785 				a->main.panning=i->panning;
2786 
2787 			a->main.handle=s->handle;
2788 			a->speed=s->speed;
2789 
2790 			if (i) {
2791 				if ((mod->panflag)&&(i->flags & IF_PITCHPAN)
2792 				   &&(a->main.panning!=PAN_SURROUND)){
2793 					a->main.panning+=
2794 					    ((a->anote-i->pitpancenter)*i->pitpansep)/8;
2795 					if (a->main.panning<PAN_LEFT)
2796 						a->main.panning=PAN_LEFT;
2797 					else if (a->main.panning>PAN_RIGHT)
2798 						a->main.panning=PAN_RIGHT;
2799 				}
2800 				a->main.pitflg=i->pitflg;
2801 				a->main.volflg=i->volflg;
2802 				a->main.panflg=i->panflg;
2803 				a->main.nna=i->nnatype;
2804 				a->dca=i->dca;
2805 				a->dct=i->dct;
2806 			} else {
2807 				a->main.pitflg=a->main.volflg=a->main.panflg=0;
2808 				a->main.nna=a->dca=0;
2809 				a->dct=DCT_OFF;
2810 			}
2811 
2812 			if (funky&2) /* instrument change */ {
2813 				/* IT random volume variations: 0:8 bit fixed, and one bit for
2814 				   sign. */
2815 				a->volume=a->tmpvolume=s->volume;
2816 				if ((s)&&(i)) {
2817 					if (i->rvolvar) {
2818 						a->volume=a->tmpvolume=s->volume+
2819 						  ((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512)
2820 						  ))/25600);
2821 						if (a->volume<0)
2822 							a->volume=a->tmpvolume=0;
2823 						else if (a->volume>64)
2824 							a->volume=a->tmpvolume=64;
2825 					}
2826 					if ((mod->panflag)&&(a->main.panning!=PAN_SURROUND)) {
2827 						a->main.panning+=((a->main.panning*((SLONG)i->rpanvar*
2828 						  (SLONG)getrandom(512)))/25600);
2829 						if (a->main.panning<PAN_LEFT)
2830 							a->main.panning=PAN_LEFT;
2831 						else if (a->main.panning>PAN_RIGHT)
2832 							a->main.panning=PAN_RIGHT;
2833 					}
2834 				}
2835 			}
2836 
2837 			a->wantedperiod=a->tmpperiod=
2838 			    GetPeriod(mod->flags, (UWORD)a->main.note<<1,a->speed);
2839 			a->main.keyoff=KEY_KICK;
2840 		}
2841 	}
2842 }
2843 
2844 /* Handles effects */
pt_EffectsPass1(MODULE * mod)2845 void pt_EffectsPass1(MODULE *mod)
2846 {
2847 	SWORD channel;
2848 	MP_CONTROL *a;
2849 	MP_VOICE *aout;
2850 	int explicitslides;
2851 
2852 	for (channel=0;channel<mod->numchn;channel++) {
2853 		a=&mod->control[channel];
2854 
2855 		if ((aout=a->slave)) {
2856 			a->main.fadevol=aout->main.fadevol;
2857 			a->main.period=aout->main.period;
2858 			if (a->main.kick==KICK_KEYOFF)
2859 				a->main.keyoff=aout->main.keyoff;
2860 		}
2861 
2862 		if (!a->row) continue;
2863 		UniSetRow(a->row);
2864 
2865 		a->ownper=a->ownvol=0;
2866 		explicitslides = pt_playeffects(mod, channel, a);
2867 
2868 		/* continue volume slide if necessary for XM and IT */
2869 		if (mod->flags&UF_BGSLIDES) {
2870 			if (!explicitslides && a->sliding)
2871 				DoS3MVolSlide(mod->vbtick, mod->flags, a, 0);
2872 			else if (a->tmpvolume)
2873 				a->sliding = explicitslides;
2874 		}
2875 
2876 		if (!a->ownper)
2877 			a->main.period=a->tmpperiod;
2878 		if (!a->ownvol)
2879 			a->volume=a->tmpvolume;
2880 
2881 		if (a->main.s) {
2882 			if (a->main.i)
2883 				a->main.outvolume=
2884 				    (a->volume*a->main.s->globvol*a->main.i->globvol)>>10;
2885 			else
2886 				a->main.outvolume=(a->volume*a->main.s->globvol)>>4;
2887 			if (a->main.outvolume>256)
2888 				a->main.outvolume=256;
2889 			else if (a->main.outvolume<0)
2890 				a->main.outvolume=0;
2891 		}
2892 	}
2893 }
2894 
2895 /* NNA management */
pt_NNA(MODULE * mod)2896 void pt_NNA(MODULE *mod)
2897 {
2898 	SWORD channel;
2899 	MP_CONTROL *a;
2900 
2901 	for (channel=0;channel<mod->numchn;channel++) {
2902 		a=&mod->control[channel];
2903 
2904 		if (a->main.kick==KICK_NOTE) {
2905 			BOOL kill=0;
2906 
2907 			if (a->slave) {
2908 				MP_VOICE *aout;
2909 
2910 				aout=a->slave;
2911 				if (aout->main.nna & NNA_MASK) {
2912 					/* Make sure the old MP_VOICE channel knows it has no
2913 					   master now ! */
2914 					a->slave=NULL;
2915 					/* assume the channel is taken by NNA */
2916 					aout->mflag=0;
2917 
2918 					switch (aout->main.nna) {
2919 					case NNA_CONTINUE: /* continue note, do nothing */
2920 						break;
2921 					case NNA_OFF: /* note off */
2922 						aout->main.keyoff|=KEY_OFF;
2923 						if ((!(aout->main.volflg & EF_ON))||
2924 							  (aout->main.volflg & EF_LOOP))
2925 							aout->main.keyoff=KEY_KILL;
2926 						break;
2927 					case NNA_FADE:
2928 						aout->main.keyoff |= KEY_FADE;
2929 						break;
2930 					}
2931 				}
2932 			}
2933 
2934 			if (a->dct!=DCT_OFF) {
2935 				int t;
2936 
2937 				for (t=0;t<md_sngchn;t++)
2938 					if ((!Voice_Stopped_internal(t))&&
2939 					   (mod->voice[t].masterchn==channel)&&
2940 					   (a->main.sample==mod->voice[t].main.sample)) {
2941 						kill=0;
2942 						switch (a->dct) {
2943 						case DCT_NOTE:
2944 							if (a->main.note==mod->voice[t].main.note)
2945 								kill=1;
2946 							break;
2947 						case DCT_SAMPLE:
2948 							if (a->main.handle==mod->voice[t].main.handle)
2949 								kill=1;
2950 							break;
2951 						case DCT_INST:
2952 							kill=1;
2953 							break;
2954 						}
2955 						if (kill)
2956 							switch (a->dca) {
2957 							case DCA_CUT:
2958 								mod->voice[t].main.fadevol=0;
2959 								break;
2960 							case DCA_OFF:
2961 								mod->voice[t].main.keyoff|=KEY_OFF;
2962 								if ((!(mod->voice[t].main.volflg&EF_ON))||
2963 								    (mod->voice[t].main.volflg&EF_LOOP))
2964 									mod->voice[t].main.keyoff=KEY_KILL;
2965 								break;
2966 							case DCA_FADE:
2967 								mod->voice[t].main.keyoff|=KEY_FADE;
2968 								break;
2969 							}
2970 					}
2971 			}
2972 		} /* if (a->main.kick==KICK_NOTE) */
2973 	}
2974 }
2975 
2976 /* Setup module and NNA voices */
pt_SetupVoices(MODULE * mod)2977 void pt_SetupVoices(MODULE *mod)
2978 {
2979 	SWORD channel;
2980 	MP_CONTROL *a;
2981 	MP_VOICE *aout;
2982 
2983 	for (channel=0;channel<mod->numchn;channel++) {
2984 		a=&mod->control[channel];
2985 
2986 		if (a->main.notedelay) continue;
2987 		if (a->main.kick==KICK_NOTE) {
2988 			/* if no channel was cut above, find an empty or quiet channel
2989 			   here */
2990 			if (mod->flags&UF_NNA) {
2991 				if (!a->slave) {
2992 					int newchn;
2993 
2994 					if ((newchn=MP_FindEmptyChannel(mod))!=-1)
2995 						a->slave=&mod->voice[a->slavechn=newchn];
2996 				}
2997 			} else
2998 				a->slave=&mod->voice[a->slavechn=channel];
2999 
3000 			/* assign parts of MP_VOICE only done for a KICK_NOTE */
3001 			if ((aout=a->slave)) {
3002 				if (aout->mflag && aout->master) aout->master->slave=NULL;
3003 				aout->master=a;
3004 				a->slave=aout;
3005 				aout->masterchn=channel;
3006 				aout->mflag=1;
3007 			}
3008 		} else
3009 			aout=a->slave;
3010 
3011 		if (aout)
3012 			aout->main=a->main;
3013 		a->main.kick=KICK_ABSENT;
3014 	}
3015 }
3016 
3017 /* second effect pass */
pt_EffectsPass2(MODULE * mod)3018 void pt_EffectsPass2(MODULE *mod)
3019 {
3020 	SWORD channel;
3021 	MP_CONTROL *a;
3022 	UBYTE c;
3023 
3024 	for (channel=0;channel<mod->numchn;channel++) {
3025 		a=&mod->control[channel];
3026 
3027 		if (!a->row) continue;
3028 		UniSetRow(a->row);
3029 
3030 		while((c=UniGetByte()))
3031 			if (c==UNI_ITEFFECTS0) {
3032 				c=UniGetByte();
3033 				if ((c>>4)==SS_S7EFFECTS)
3034 					DoNNAEffects(mod, a, c&0xf);
3035 			} else
3036 				UniSkipOpcode();
3037 	}
3038 }
3039 
Player_HandleTick(void)3040 void Player_HandleTick(void)
3041 {
3042 	SWORD channel;
3043 	int max_volume;
3044 
3045 #if 0
3046 	/* don't handle the very first ticks, this allows the other hardware to
3047 	   settle down so we don't loose any starting notes */
3048 	if (isfirst) {
3049 		isfirst--;
3050 		return;
3051 	}
3052 #endif
3053 
3054 	if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return;
3055 
3056 	/* update time counter (sngtime is in milliseconds (in fact 2^-10)) */
3057 	pf->sngremainder+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */
3058 	pf->sngtime+=pf->sngremainder/pf->bpm;
3059 	pf->sngremainder%=pf->bpm;
3060 
3061 	if (++pf->vbtick>=pf->sngspd) {
3062 		if (pf->pat_repcrazy)
3063 			pf->pat_repcrazy=0; /* play 2 times row 0 */
3064 		else
3065 			pf->patpos++;
3066 		pf->vbtick=0;
3067 
3068 		/* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
3069 		   the command memory. */
3070 		if (pf->patdly)
3071 			pf->patdly2=pf->patdly,pf->patdly=0;
3072 		if (pf->patdly2) {
3073 			/* patterndelay active */
3074 			if (--pf->patdly2)
3075 				/* so turn back pf->patpos by 1 */
3076 				if (pf->patpos) pf->patpos--;
3077 		}
3078 
3079 		/* do we have to get a new patternpointer ? (when pf->patpos reaches the
3080 		   pattern size, or when a patternbreak is active) */
3081 		if (((pf->patpos>=pf->numrow)&&(pf->numrow>0))&&(!pf->posjmp))
3082 			pf->posjmp=3;
3083 
3084 		if (pf->posjmp) {
3085 			pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0;
3086 			pf->pat_repcrazy=0;
3087 			pf->sngpos+=(pf->posjmp-2);
3088 			for (channel=0;channel<pf->numchn;channel++)
3089 				pf->control[channel].pat_reppos=-1;
3090 
3091 			pf->patbrk=pf->posjmp=0;
3092 			/* handle the "---" (end of song) pattern since it can occur
3093 			   *inside* the module in some formats */
3094 			if ((pf->sngpos>=pf->numpos)||
3095 				(pf->positions[pf->sngpos]==LAST_PATTERN)) {
3096 				if (!pf->wrap) return;
3097 				if (!(pf->sngpos=pf->reppos)) {
3098 				    pf->volume=pf->initvolume>128?128:pf->initvolume;
3099 					if(pf->initspeed!=0)
3100 						pf->sngspd=pf->initspeed<32?pf->initspeed:32;
3101 					else
3102 						pf->sngspd=6;
3103 					pf->bpm=pf->inittempo<32?32:pf->inittempo;
3104 				}
3105 			}
3106 			if (pf->sngpos<0) pf->sngpos=pf->numpos-1;
3107 		}
3108 
3109 		if (!pf->patdly2)
3110 			pt_Notes(pf);
3111 	}
3112 
3113 	/* Fade global volume if enabled and we're playing the last pattern */
3114 	if (((pf->sngpos==pf->numpos-1)||
3115 		 (pf->positions[pf->sngpos+1]==LAST_PATTERN))&&
3116 	    (pf->fadeout))
3117 		max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0;
3118 	else
3119 		max_volume=128;
3120 
3121 	pt_EffectsPass1(pf);
3122 	if (pf->flags&UF_NNA)
3123 		pt_NNA(pf);
3124 	pt_SetupVoices(pf);
3125 	pt_EffectsPass2(pf);
3126 
3127 	/* now set up the actual hardware channel playback information */
3128 	pt_UpdateVoices(pf, max_volume);
3129 }
3130 
Player_Init_internal(MODULE * mod)3131 static void Player_Init_internal(MODULE* mod)
3132 {
3133 	int t;
3134 
3135 	for (t=0;t<mod->numchn;t++) {
3136 		mod->control[t].main.chanvol=mod->chanvol[t];
3137 		mod->control[t].main.panning=mod->panning[t];
3138 	}
3139 
3140 	mod->sngtime=0;
3141 	mod->sngremainder=0;
3142 
3143 	mod->pat_repcrazy=0;
3144 	mod->sngpos=0;
3145 	if(mod->initspeed!=0)
3146 		mod->sngspd=mod->initspeed<32?mod->initspeed:32;
3147 	else
3148 		mod->sngspd=6;
3149 	mod->volume=mod->initvolume>128?128:mod->initvolume;
3150 
3151 	mod->vbtick=mod->sngspd;
3152 	mod->patdly=0;
3153 	mod->patdly2=0;
3154 	mod->bpm=mod->inittempo<32?32:mod->inittempo;
3155 	mod->realchn=0;
3156 
3157 	mod->patpos=0;
3158 	mod->posjmp=2; /* make sure the player fetches the first note */
3159 	mod->numrow=-1;
3160 	mod->patbrk=0;
3161 }
3162 
Player_Init(MODULE * mod)3163 BOOL Player_Init(MODULE* mod)
3164 {
3165 	mod->extspd=1;
3166 	mod->panflag=1;
3167 	mod->wrap=0;
3168 	mod->loop=1;
3169 	mod->fadeout=0;
3170 
3171 	mod->relspd=0;
3172 
3173 	/* make sure the player doesn't start with garbage */
3174 	if (!(mod->control=(MP_CONTROL*)MikMod_calloc(mod->numchn,sizeof(MP_CONTROL))))
3175 		return 1;
3176 	if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE))))
3177 		return 1;
3178 
3179 	Player_Init_internal(mod);
3180 	return 0;
3181 }
3182 
Player_Exit_internal(MODULE * mod)3183 void Player_Exit_internal(MODULE* mod)
3184 {
3185 	if (!mod)
3186 		return;
3187 
3188 	/* Stop playback if necessary */
3189 	if (mod==pf) {
3190 		Player_Stop_internal();
3191 		pf=NULL;
3192 	}
3193 
3194 	if (mod->control)
3195 		MikMod_free(mod->control);
3196 	if (mod->voice)
3197 		MikMod_free(mod->voice);
3198 	mod->control=NULL;
3199 	mod->voice=NULL;
3200 }
3201 
Player_Exit(MODULE * mod)3202 void Player_Exit(MODULE* mod)
3203 {
3204 	MUTEX_LOCK(vars);
3205 	Player_Exit_internal(mod);
3206 	MUTEX_UNLOCK(vars);
3207 }
3208 
Player_SetVolume(SWORD volume)3209 MIKMODAPI void Player_SetVolume(SWORD volume)
3210 {
3211 	MUTEX_LOCK(vars);
3212 	if (pf)
3213 		pf->volume=(volume<0)?0:(volume>128)?128:volume;
3214 	MUTEX_UNLOCK(vars);
3215 }
3216 
Player_GetModule(void)3217 MIKMODAPI MODULE* Player_GetModule(void)
3218 {
3219 	MODULE* result;
3220 
3221 	MUTEX_LOCK(vars);
3222 	result=pf;
3223 	MUTEX_UNLOCK(vars);
3224 
3225 	return result;
3226 }
3227 
Player_Start(MODULE * mod)3228 MIKMODAPI void Player_Start(MODULE *mod)
3229 {
3230 	int t;
3231 
3232 	if (!mod)
3233 		return;
3234 
3235 	if (!MikMod_Active())
3236 		MikMod_EnableOutput();
3237 
3238 	mod->forbid=0;
3239 
3240 	MUTEX_LOCK(vars);
3241 	if (pf!=mod) {
3242 		/* new song is being started, so completely stop out the old one. */
3243 		if (pf) pf->forbid=1;
3244 		for (t=0;t<md_sngchn;t++) Voice_Stop_internal(t);
3245 	}
3246 	pf=mod;
3247 	MUTEX_UNLOCK(vars);
3248 }
3249 
Player_Stop_internal(void)3250 void Player_Stop_internal(void)
3251 {
3252 	if (!md_sfxchn) MikMod_DisableOutput_internal();
3253 	if (pf) pf->forbid=1;
3254 	pf=NULL;
3255 }
3256 
Player_Stop(void)3257 MIKMODAPI void Player_Stop(void)
3258 {
3259 	MUTEX_LOCK(vars);
3260 		Player_Stop_internal();
3261 	MUTEX_UNLOCK(vars);
3262 }
3263 
Player_Active(void)3264 MIKMODAPI BOOL Player_Active(void)
3265 {
3266 	BOOL result=0;
3267 
3268 	MUTEX_LOCK(vars);
3269 	if (pf)
3270 		result=(!(pf->sngpos>=pf->numpos));
3271 	MUTEX_UNLOCK(vars);
3272 
3273 	return result;
3274 }
3275 
Player_NextPosition(void)3276 MIKMODAPI void Player_NextPosition(void)
3277 {
3278 	MUTEX_LOCK(vars);
3279 	if (pf) {
3280 		int t;
3281 
3282 		pf->forbid=1;
3283 		pf->posjmp=3;
3284 		pf->patbrk=0;
3285 		pf->vbtick=pf->sngspd;
3286 
3287 		for (t=0;t<md_sngchn;t++) {
3288 			Voice_Stop_internal(t);
3289 			pf->voice[t].main.i=NULL;
3290 			pf->voice[t].main.s=NULL;
3291 		}
3292 		for (t=0;t<pf->numchn;t++) {
3293 			pf->control[t].main.i=NULL;
3294 			pf->control[t].main.s=NULL;
3295 		}
3296 		pf->forbid=0;
3297 	}
3298 	MUTEX_UNLOCK(vars);
3299 }
3300 
Player_PrevPosition(void)3301 MIKMODAPI void Player_PrevPosition(void)
3302 {
3303 	MUTEX_LOCK(vars);
3304 	if (pf) {
3305 		int t;
3306 
3307 		pf->forbid=1;
3308 		pf->posjmp=1;
3309 		pf->patbrk=0;
3310 		pf->vbtick=pf->sngspd;
3311 
3312 		for (t=0;t<md_sngchn;t++) {
3313 			Voice_Stop_internal(t);
3314 			pf->voice[t].main.i=NULL;
3315 			pf->voice[t].main.s=NULL;
3316 		}
3317 		for (t=0;t<pf->numchn;t++) {
3318 			pf->control[t].main.i=NULL;
3319 			pf->control[t].main.s=NULL;
3320 		}
3321 		pf->forbid=0;
3322 	}
3323 	MUTEX_UNLOCK(vars);
3324 }
3325 
Player_SetPosition(UWORD pos)3326 MIKMODAPI void Player_SetPosition(UWORD pos)
3327 {
3328 	MUTEX_LOCK(vars);
3329 	if (pf) {
3330 		int t;
3331 
3332 		pf->forbid=1;
3333 		if (pos>=pf->numpos) pos=pf->numpos;
3334 		pf->posjmp=2;
3335 		pf->patbrk=0;
3336 		pf->sngpos=pos;
3337 		pf->vbtick=pf->sngspd;
3338 
3339 		for (t=0;t<md_sngchn;t++) {
3340 			Voice_Stop_internal(t);
3341 			pf->voice[t].main.i=NULL;
3342 			pf->voice[t].main.s=NULL;
3343 		}
3344 		for (t=0;t<pf->numchn;t++) {
3345 			pf->control[t].main.i=NULL;
3346 			pf->control[t].main.s=NULL;
3347 		}
3348 		pf->forbid=0;
3349 
3350 		if (!pos)
3351 			Player_Init_internal(pf);
3352 	}
3353 	MUTEX_UNLOCK(vars);
3354 }
3355 
Player_Unmute_internal(SLONG arg1,va_list ap)3356 static void Player_Unmute_internal(SLONG arg1,va_list ap)
3357 {
3358 	SLONG t,arg2,arg3=0;
3359 
3360 	if (pf) {
3361 		switch (arg1) {
3362 		case MUTE_INCLUSIVE:
3363 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3364 			   (arg2>arg3)||(arg3>=pf->numchn))
3365 				return;
3366 			for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3367 				pf->control[arg2].muted=0;
3368 			break;
3369 		case MUTE_EXCLUSIVE:
3370 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3371 			   (arg2>arg3)||(arg3>=pf->numchn))
3372 				return;
3373 			for (t=0;t<pf->numchn;t++) {
3374 				if ((t>=arg2) && (t<=arg3))
3375 					continue;
3376 				pf->control[t].muted=0;
3377 			}
3378 			break;
3379 		default:
3380 			if (arg1<pf->numchn) pf->control[arg1].muted=0;
3381 			break;
3382 		}
3383 	}
3384 }
3385 
Player_Unmute(SLONG arg1,...)3386 MIKMODAPI void Player_Unmute(SLONG arg1, ...)
3387 {
3388 	va_list args;
3389 
3390 	va_start(args,arg1);
3391 	MUTEX_LOCK(vars);
3392 	Player_Unmute_internal(arg1,args);
3393 	MUTEX_UNLOCK(vars);
3394 	va_end(args);
3395 }
3396 
Player_Mute_internal(SLONG arg1,va_list ap)3397 static void Player_Mute_internal(SLONG arg1,va_list ap)
3398 {
3399 	SLONG t,arg2,arg3=0;
3400 
3401 	if (pf) {
3402 		switch (arg1) {
3403 		case MUTE_INCLUSIVE:
3404 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3405 			    (arg2>arg3)||(arg3>=pf->numchn))
3406 				return;
3407 			for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3408 				pf->control[arg2].muted=1;
3409 			break;
3410 		case MUTE_EXCLUSIVE:
3411 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3412 			    (arg2>arg3)||(arg3>=pf->numchn))
3413 				return;
3414 			for (t=0;t<pf->numchn;t++) {
3415 				if ((t>=arg2) && (t<=arg3))
3416 					continue;
3417 				pf->control[t].muted=1;
3418 			}
3419 			break;
3420 		default:
3421 			if (arg1<pf->numchn)
3422 				pf->control[arg1].muted=1;
3423 			break;
3424 		}
3425 	}
3426 }
3427 
Player_Mute(SLONG arg1,...)3428 MIKMODAPI void Player_Mute(SLONG arg1,...)
3429 {
3430 	va_list args;
3431 
3432 	va_start(args,arg1);
3433 	MUTEX_LOCK(vars);
3434 	Player_Mute_internal(arg1,args);
3435 	MUTEX_UNLOCK(vars);
3436 	va_end(args);
3437 }
3438 
Player_ToggleMute_internal(SLONG arg1,va_list ap)3439 static void Player_ToggleMute_internal(SLONG arg1,va_list ap)
3440 {
3441 	SLONG arg2,arg3=0;
3442 	SLONG t;
3443 
3444 	if (pf) {
3445 		switch (arg1) {
3446 		case MUTE_INCLUSIVE:
3447 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3448 			    (arg2>arg3)||(arg3>=pf->numchn))
3449 				return;
3450 			for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3451 				pf->control[arg2].muted=1-pf->control[arg2].muted;
3452 			break;
3453 		case MUTE_EXCLUSIVE:
3454 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3455 			    (arg2>arg3)||(arg3>=pf->numchn))
3456 				return;
3457 			for (t=0;t<pf->numchn;t++) {
3458 				if ((t>=arg2) && (t<=arg3))
3459 					continue;
3460 				pf->control[t].muted=1-pf->control[t].muted;
3461 			}
3462 			break;
3463 		default:
3464 			if (arg1<pf->numchn)
3465 				pf->control[arg1].muted=1-pf->control[arg1].muted;
3466 			break;
3467 		}
3468 	}
3469 }
3470 
Player_ToggleMute(SLONG arg1,...)3471 MIKMODAPI void Player_ToggleMute(SLONG arg1,...)
3472 {
3473 	va_list args;
3474 
3475 	va_start(args,arg1);
3476 	MUTEX_LOCK(vars);
3477 	Player_ToggleMute_internal(arg1,args);
3478 	MUTEX_UNLOCK(vars);
3479 	va_end(args);
3480 }
3481 
Player_Muted(UBYTE chan)3482 MIKMODAPI BOOL Player_Muted(UBYTE chan)
3483 {
3484 	BOOL result=1;
3485 
3486 	MUTEX_LOCK(vars);
3487 	if (pf)
3488 		result=(chan<pf->numchn)?pf->control[chan].muted:1;
3489 	MUTEX_UNLOCK(vars);
3490 
3491 	return result;
3492 }
3493 
Player_GetChannelVoice(UBYTE chan)3494 MIKMODAPI int Player_GetChannelVoice(UBYTE chan)
3495 {
3496 	int result=0;
3497 
3498 	MUTEX_LOCK(vars);
3499 	if (pf)
3500 		result=(chan<pf->numchn)?pf->control[chan].slavechn:-1;
3501 	MUTEX_UNLOCK(vars);
3502 
3503 	return result;
3504 }
3505 
Player_GetChannelPeriod(UBYTE chan)3506 MIKMODAPI UWORD Player_GetChannelPeriod(UBYTE chan)
3507 {
3508 	UWORD result=0;
3509 
3510 	MUTEX_LOCK(vars);
3511     if (pf)
3512 	    result=(chan<pf->numchn)?pf->control[chan].main.period:0;
3513 	MUTEX_UNLOCK(vars);
3514 
3515 	return result;
3516 }
3517 
Player_Paused_internal(void)3518 BOOL Player_Paused_internal(void)
3519 {
3520 	return pf?pf->forbid:1;
3521 }
3522 
Player_Paused(void)3523 MIKMODAPI BOOL Player_Paused(void)
3524 {
3525 	BOOL result;
3526 
3527 	MUTEX_LOCK(vars);
3528 	result=Player_Paused_internal();
3529 	MUTEX_UNLOCK(vars);
3530 
3531 	return result;
3532 }
3533 
Player_TogglePause(void)3534 MIKMODAPI void Player_TogglePause(void)
3535 {
3536 	MUTEX_LOCK(vars);
3537 	if (pf)
3538 		pf->forbid=1-pf->forbid;
3539 	MUTEX_UNLOCK(vars);
3540 }
3541 
Player_SetSpeed(UWORD speed)3542 MIKMODAPI void Player_SetSpeed(UWORD speed)
3543 {
3544 	MUTEX_LOCK(vars);
3545 	if (pf)
3546 		pf->sngspd=speed?(speed<32?speed:32):1;
3547 	MUTEX_UNLOCK(vars);
3548 }
3549 
Player_SetTempo(UWORD tempo)3550 MIKMODAPI void Player_SetTempo(UWORD tempo)
3551 {
3552 	if (tempo<32) tempo=32;
3553 	MUTEX_LOCK(vars);
3554 	if (pf) {
3555 		if ((!(pf->flags&UF_HIGHBPM))&&(tempo>255)) tempo=255;
3556 		pf->bpm=tempo;
3557 	}
3558 	MUTEX_UNLOCK(vars);
3559 }
3560 
3561 /* ex:set ts=4: */
3562