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 MODULE *pf = NULL;
52 
53 #define NUMVOICES(mod) (md_sngchn < (mod)->numvoices ? md_sngchn : (mod)->numvoices)
54 
55 #define	HIGH_OCTAVE		2	/* number of above-range octaves */
56 
57 static	const 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	const 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	const 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	const 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	const 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	const 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 ceilval)230 static int getrandom(int ceilval)
231 {
232 #if defined(HAVE_SRANDOM) && !defined(_MIKMOD_AMIGA)
233 	return random()&(ceilval-1);
234 #else
235 	return (rand()*ceilval)/(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<NUMVOICES(mod);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<NUMVOICES(mod);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++;
367 		t->b++;
368 	}
369 
370 	/* Fit in the envelope, still */
371 	if (t->a >= t->pts)
372 		t->a = t->pts - 1;
373 	if (t->b >= t->pts)
374 		t->b = t->pts-1;
375 
376 	return t->env[t->a].val;
377 }
378 
379 /* This procedure processes all envelope types, include volume, pitch, and
380    panning.  Envelopes are defined by a set of points, each with a magnitude
381    [relating either to volume, panning position, or pitch modifier] and a tick
382    position.
383 
384    Envelopes work in the following manner:
385 
386    (a) Each tick the envelope is moved a point further in its progression. For
387        an accurate progression, magnitudes between two envelope points are
388        interpolated.
389 
390    (b) When progression reaches a defined point on the envelope, values are
391        shifted to interpolate between this point and the next, and checks for
392        loops or envelope end are done.
393 
394    Misc:
395      Sustain loops are loops that are only active as long as the keyoff flag is
396      clear.  When a volume envelope terminates, so does the current fadeout.
397 */
ProcessEnvelope(MP_VOICE * aout,ENVPR * t,SWORD v)398 static SWORD ProcessEnvelope(MP_VOICE *aout, ENVPR *t, SWORD v)
399 {
400 	if (t->flg & EF_ON) {
401 		UBYTE a, b;		/* actual points in the envelope */
402 		UWORD p;		/* the 'tick counter' - real point being played */
403 
404 		a = t->a;
405 		b = t->b;
406 		p = t->p;
407 
408 		/*
409 		 * Sustain loop on one point (XM type).
410 		 * Not processed if KEYOFF.
411 		 * Don't move and don't interpolate when the point is reached
412 		 */
413 		if ((t->flg & EF_SUSTAIN) && t->susbeg == t->susend &&
414 		   (!(aout->main.keyoff & KEY_OFF) && p == t->env[t->susbeg].pos)) {
415 			v = t->env[t->susbeg].val;
416 		} else {
417 			/*
418 			 * All following situations will require interpolation between
419 			 * two envelope points.
420 			 */
421 
422 			/*
423 			 * Sustain loop between two points (IT type).
424 			 * Not processed if KEYOFF.
425 			 */
426 			/* if we were on a loop point, loop now */
427 			if ((t->flg & EF_SUSTAIN) && !(aout->main.keyoff & KEY_OFF) &&
428 			   a >= t->susend) {
429 				a = t->susbeg;
430 				b = (t->susbeg==t->susend)?a:a+1;
431 				p = t->env[a].pos;
432 				v = t->env[a].val;
433 			} else
434 			/*
435 			 * Regular loop.
436 			 * Be sure to correctly handle single point loops.
437 			 */
438 			if ((t->flg & EF_LOOP) && a >= t->end) {
439 				a = t->beg;
440 				b = t->beg == t->end ? a : a + 1;
441 				p = t->env[a].pos;
442 				v = t->env[a].val;
443 			} else
444 			/*
445 			 * Non looping situations.
446 			 */
447 			if (a != b)
448 				v = InterpolateEnv(p, &t->env[a], &t->env[b]);
449 			else
450 				v = t->env[a].val;
451 
452 			/*
453 			 * Start to fade if the volume envelope is finished.
454 			 */
455 			if (p >= t->env[t->pts - 1].pos) {
456 				if (t->flg & EF_VOLENV) {
457 					aout->main.keyoff |= KEY_FADE;
458 					if (!v)
459 						aout->main.fadevol = 0;
460 				}
461 			} else {
462 				p++;
463 				/* did pointer reach point b? */
464 				if (p >= t->env[b].pos)
465 					a = b++; /* shift points a and b */
466 			}
467 			t->a = a;
468 			t->b = b;
469 			t->p = p;
470 		}
471 	}
472 	return v;
473 }
474 
475 /* XM linear period to frequency conversion */
getfrequency(UWORD flags,ULONG period)476 ULONG getfrequency(UWORD flags,ULONG period)
477 {
478 	if (flags & UF_LINEAR) {
479 		SLONG shift = ((SLONG)period / 768) - HIGH_OCTAVE;
480 
481 		if (shift >= 0)
482 			return lintab[period % 768] >> shift;
483 		else
484 			return lintab[period % 768] << (-shift);
485 	} else
486 		return (8363L*1712L)/(period?period:1);
487 }
488 
489 /*========== Protracker effects */
490 
DoArpeggio(UWORD tick,UWORD flags,MP_CONTROL * a,UBYTE style)491 static void DoArpeggio(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE style)
492 {
493 	UBYTE note=a->main.note;
494 
495 	if (a->arpmem) {
496 		switch (style) {
497 		case 0:		/* mod style: N, N+x, N+y */
498 			switch (tick % 3) {
499 			/* case 0: unchanged */
500 			case 1:
501 				note += (a->arpmem >> 4);
502 				break;
503 			case 2:
504 				note += (a->arpmem & 0xf);
505 				break;
506 			}
507 			break;
508 		case 3:		/* okt arpeggio 3: N-x, N, N+y */
509 			switch (tick % 3) {
510 			case 0:
511 				note -= (a->arpmem >> 4);
512 				break;
513 			/* case 1: unchanged */
514 			case 2:
515 				note += (a->arpmem & 0xf);
516 				break;
517 			}
518 			break;
519 		case 4:		/* okt arpeggio 4: N, N+y, N, N-x */
520 			switch (tick % 4) {
521 			/* case 0, case 2: unchanged */
522 			case 1:
523 				note += (a->arpmem & 0xf);
524 				break;
525 			case 3:
526 				note -= (a->arpmem >> 4);
527 				break;
528 			}
529 			break;
530 		case 5:		/* okt arpeggio 5: N-x, N+y, N, and nothing at tick 0 */
531 			if (!tick)
532 				break;
533 			switch (tick % 3) {
534 			/* case 0: unchanged */
535 			case 1:
536 				note -= (a->arpmem >> 4);
537 				break;
538 			case 2:
539 				note += (a->arpmem & 0xf);
540 				break;
541 			}
542 			break;
543 		}
544 		a->main.period = GetPeriod(flags, (UWORD)note << 1, a->speed);
545 		a->ownper = 1;
546 	}
547 }
548 
DoPTEffect0(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)549 static int DoPTEffect0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
550 {
551 	UBYTE dat;
552 
553 	dat = UniGetByte();
554 	if (!tick) {
555 		if (!dat && (flags & UF_ARPMEM))
556 			dat=a->arpmem;
557 		else
558 			a->arpmem=dat;
559 	}
560 	if (a->main.period)
561 		DoArpeggio(tick, flags, a, 0);
562 
563 	return 0;
564 }
565 
DoPTEffect1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)566 static int DoPTEffect1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
567 {
568 	UBYTE dat;
569 
570 	dat = UniGetByte();
571 	if (!tick && dat)
572 		a->slidespeed = (UWORD)dat << 2;
573 	if (a->main.period)
574 		if (tick)
575 			a->tmpperiod -= a->slidespeed;
576 
577 	return 0;
578 }
579 
DoPTEffect2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)580 static int DoPTEffect2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
581 {
582 	UBYTE dat;
583 
584 	dat = UniGetByte();
585 	if (!tick && dat)
586 		a->slidespeed = (UWORD)dat << 2;
587 	if (a->main.period)
588 		if (tick)
589 			a->tmpperiod += a->slidespeed;
590 
591 	return 0;
592 }
593 
DoToneSlide(UWORD tick,MP_CONTROL * a)594 static void DoToneSlide(UWORD tick, MP_CONTROL *a)
595 {
596 	if (!a->main.fadevol)
597 		a->main.kick = (a->main.kick == KICK_NOTE)? KICK_NOTE : KICK_KEYOFF;
598 	else
599 		a->main.kick = (a->main.kick == KICK_NOTE)? KICK_ENV : KICK_ABSENT;
600 
601 	if (tick != 0) {
602 		int dist;
603 
604 		/* We have to slide a->main.period towards a->wantedperiod, so compute
605 		   the difference between those two values */
606 		dist=a->main.period-a->wantedperiod;
607 
608 		/* if they are equal or if portamentospeed is too big ...*/
609 		if (dist == 0 || a->portspeed > abs(dist))
610 			/* ...make tmpperiod equal tperiod */
611 			a->tmpperiod=a->main.period=a->wantedperiod;
612 		else if (dist>0) {
613 			a->tmpperiod-=a->portspeed;
614 			a->main.period-=a->portspeed; /* dist>0, slide up */
615 		} else {
616 			a->tmpperiod+=a->portspeed;
617 			a->main.period+=a->portspeed; /* dist<0, slide down */
618 		}
619 	} else
620 		a->tmpperiod=a->main.period;
621 	a->ownper = 1;
622 }
623 
DoPTEffect3(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)624 static int DoPTEffect3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
625 {
626 	UBYTE dat;
627 
628 	dat=UniGetByte();
629 	if ((!tick)&&(dat)) a->portspeed=(UWORD)dat<<2;
630 	if (a->main.period)
631 		DoToneSlide(tick, a);
632 
633 	return 0;
634 }
635 
DoVibrato(UWORD tick,MP_CONTROL * a)636 static void DoVibrato(UWORD tick, MP_CONTROL *a)
637 {
638 	UBYTE q;
639 	UWORD temp = 0;	/* silence warning */
640 
641 	if (!tick)
642 		return;
643 
644 	q=(a->vibpos>>2)&0x1f;
645 
646 	switch (a->wavecontrol&3) {
647 	case 0: /* sine */
648 		temp=VibratoTable[q];
649 		break;
650 	case 1: /* ramp down */
651 		q<<=3;
652 		if (a->vibpos<0) q=255-q;
653 		temp=q;
654 		break;
655 	case 2: /* square wave */
656 		temp=255;
657 		break;
658 	case 3: /* random wave */
659 		temp=getrandom(256);
660 		break;
661 	}
662 
663 	temp*=a->vibdepth;
664 	temp>>=7;temp<<=2;
665 
666 	if (a->vibpos>=0)
667 		a->main.period=a->tmpperiod+temp;
668 	else
669 		a->main.period=a->tmpperiod-temp;
670 	a->ownper = 1;
671 
672 	if (tick != 0)
673 		a->vibpos+=a->vibspd;
674 }
675 
DoPTEffect4(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)676 static int DoPTEffect4(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
677 {
678 	UBYTE dat;
679 
680 	dat=UniGetByte();
681 	if (!tick) {
682 		if (dat&0x0f) a->vibdepth=dat&0xf;
683 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
684 	}
685 	if (a->main.period)
686 		DoVibrato(tick, a);
687 
688 	return 0;
689 }
690 
DoVolSlide(MP_CONTROL * a,UBYTE dat)691 static void DoVolSlide(MP_CONTROL *a, UBYTE dat)
692 {
693 	if (dat&0xf) {
694 		a->tmpvolume-=(dat&0x0f);
695 		if (a->tmpvolume<0)
696 			a->tmpvolume=0;
697 	} else {
698 		a->tmpvolume+=(dat>>4);
699 		if (a->tmpvolume>64)
700 			a->tmpvolume=64;
701 	}
702 }
703 
DoPTEffect5(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)704 static int DoPTEffect5(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
705 {
706 	UBYTE dat;
707 
708 	dat=UniGetByte();
709 	if (a->main.period)
710 		DoToneSlide(tick, a);
711 
712 	if (tick)
713 		DoVolSlide(a, dat);
714 
715 	return 0;
716 }
717 
718 /* DoPTEffect6 after DoPTEffectA */
719 
DoPTEffect7(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)720 static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
721 {
722 	UBYTE dat;
723 	UBYTE q;
724 	UWORD temp = 0;	/* silence warning */
725 
726 	dat=UniGetByte();
727 	if (!tick) {
728 		if (dat&0x0f) a->trmdepth=dat&0xf;
729 		if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
730 	}
731 	if (a->main.period) {
732 		q=(a->trmpos>>2)&0x1f;
733 
734 		switch ((a->wavecontrol>>4)&3) {
735 		case 0: /* sine */
736 			temp=VibratoTable[q];
737 			break;
738 		case 1: /* ramp down */
739 			q<<=3;
740 			if (a->trmpos<0) q=255-q;
741 			temp=q;
742 			break;
743 		case 2: /* square wave */
744 			temp=255;
745 			break;
746 		case 3: /* random wave */
747 			temp=getrandom(256);
748 			break;
749 		}
750 		temp*=a->trmdepth;
751 		temp>>=6;
752 
753 		if (a->trmpos>=0) {
754 			a->volume=a->tmpvolume+temp;
755 			if (a->volume>64) a->volume=64;
756 		} else {
757 			a->volume=a->tmpvolume-temp;
758 			if (a->volume<0) a->volume=0;
759 		}
760 		a->ownvol = 1;
761 
762 		if (tick)
763 			a->trmpos+=a->trmspd;
764 	}
765 
766 	return 0;
767 }
768 
DoPTEffect8(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)769 static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
770 {
771 	UBYTE dat;
772 
773 	dat = UniGetByte();
774 	if (mod->panflag)
775 		a->main.panning = mod->panning[channel] = dat;
776 
777 	return 0;
778 }
779 
DoPTEffect9(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)780 static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
781 {
782 	UBYTE dat;
783 
784 	dat=UniGetByte();
785 	if (!tick) {
786 		if (dat) a->soffset=(UWORD)dat<<8;
787 		a->main.start=a->hioffset|a->soffset;
788 
789 		if ((a->main.s)&&(a->main.start>a->main.s->length))
790 			a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
791 			    a->main.s->loopstart:a->main.s->length;
792 	}
793 
794 	return 0;
795 }
796 
DoPTEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)797 static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
798 {
799 	UBYTE dat;
800 
801 	dat=UniGetByte();
802 	if (tick)
803 		DoVolSlide(a, dat);
804 
805 	return 0;
806 }
807 
DoPTEffect6(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)808 static int DoPTEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
809 {
810 	if (a->main.period)
811 		DoVibrato(tick, a);
812 	DoPTEffectA(tick, flags, a, mod, channel);
813 
814 	return 0;
815 }
816 
DoPTEffectB(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)817 static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
818 {
819 	UBYTE dat;
820 
821 	dat=UniGetByte();
822 
823 	if (tick || mod->patdly2)
824 		return 0;
825 
826 	/* Vincent Voois uses a nasty trick in "Universal Bolero" */
827 	if (dat == mod->sngpos && mod->patbrk == mod->patpos)
828 		return 0;
829 
830 	if (!mod->loop && !mod->patbrk &&
831 	    (dat < mod->sngpos ||
832 		 (mod->sngpos == (mod->numpos - 1) && !mod->patbrk) ||
833 	     (dat == mod->sngpos && (flags & UF_NOWRAP)) ) )
834 	{
835 		/* if we don't loop, better not to skip the end of the
836 		   pattern, after all... so:
837 		mod->patbrk=0; */
838 		mod->posjmp=3;
839 	} else {
840 		/* if we were fading, adjust... */
841 		if (mod->sngpos == (mod->numpos-1))
842 			mod->volume=mod->initvolume>128?128:mod->initvolume;
843 		mod->sngpos=dat;
844 		mod->posjmp=2;
845 		mod->patpos=0;
846 		/* cancel the FT2 pattern loop (E60) bug.
847 		 * also see DoEEffects() below for it. */
848 		if (flags & UF_FT2QUIRKS) mod->patbrk=0;
849 	}
850 
851 	return 0;
852 }
853 
DoPTEffectC(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)854 static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
855 {
856 	UBYTE dat;
857 
858 	dat=UniGetByte();
859 	if (tick) return 0;
860 	if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
861 	else if (dat>64) dat=64;
862 	a->tmpvolume=dat;
863 
864 	return 0;
865 }
866 
DoPTEffectD(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)867 static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
868 {
869 	UBYTE dat;
870 
871 	dat=UniGetByte();
872 	if ((tick)||(mod->patdly2)) return 0;
873 	if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&&
874 	    (dat>mod->pattrows[mod->positions[mod->sngpos]])) {
875 		dat=mod->pattrows[mod->positions[mod->sngpos]];
876 	}
877 	mod->patbrk=dat;
878 	if (!mod->posjmp) {
879 		/* don't ask me to explain this code - it makes
880 		   backwards.s3m and children.xm (heretic's version) play
881 		   correctly, among others. Take that for granted, or write
882 		   the page of comments yourself... you might need some
883 		   aspirin - Miod */
884 		if ((mod->sngpos==mod->numpos-1)&&(dat)&&
885 		    ((mod->loop) || (mod->positions[mod->sngpos]==(mod->numpat-1) && !(flags&UF_NOWRAP)))) {
886 			mod->sngpos=0;
887 			mod->posjmp=2;
888 		} else
889 			mod->posjmp=3;
890 	}
891 
892 	return 0;
893 }
894 
DoEEffects(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel,UBYTE dat)895 static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod,
896 	SWORD channel, UBYTE dat)
897 {
898 	UBYTE nib = dat & 0xf;
899 
900 	switch (dat>>4) {
901 	case 0x0: /* hardware filter toggle, not supported */
902 		break;
903 	case 0x1: /* fineslide up */
904 		if (a->main.period)
905 			if (!tick)
906 				a->tmpperiod-=(nib<<2);
907 		break;
908 	case 0x2: /* fineslide dn */
909 		if (a->main.period)
910 			if (!tick)
911 				a->tmpperiod+=(nib<<2);
912 		break;
913 	case 0x3: /* glissando ctrl */
914 		a->glissando=nib;
915 		break;
916 	case 0x4: /* set vibrato waveform */
917 		a->wavecontrol&=0xf0;
918 		a->wavecontrol|=nib;
919 		break;
920 	case 0x5: /* set finetune */
921 		if (a->main.period) {
922 			if (flags&UF_XMPERIODS)
923 				a->speed=nib+128;
924 			else
925 				a->speed=finetune[nib];
926 			a->tmpperiod=GetPeriod(flags, (UWORD)a->main.note<<1,a->speed);
927 		}
928 		break;
929 	case 0x6: /* set patternloop */
930 		if (tick)
931 			break;
932 		if (nib) { /* set reppos or repcnt ? */
933 			/* set repcnt, so check if repcnt already is set, which means we
934 			   are already looping */
935 			if (a->pat_repcnt)
936 				a->pat_repcnt--; /* already looping, decrease counter */
937 			else {
938 #if 0
939 				/* this would make walker.xm, shipped with Xsoundtracker,
940 				   play correctly, but it's better to remain compatible
941 				   with FT2 */
942 				if ((!(flags&UF_NOWRAP))||(a->pat_reppos!=POS_NONE))
943 #endif
944 					a->pat_repcnt=nib; /* not yet looping, so set repcnt */
945 			}
946 
947 			if (a->pat_repcnt) { /* jump to reppos if repcnt>0 */
948 				if (a->pat_reppos==POS_NONE)
949 					a->pat_reppos=mod->patpos-1;
950 				if (a->pat_reppos==-1) {
951 					mod->pat_repcrazy=1;
952 					mod->patpos=0;
953 				} else
954 					mod->patpos=a->pat_reppos;
955 			} else a->pat_reppos=POS_NONE;
956 		} else {
957 			a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */
958 			/* emulate the FT2 pattern loop (E60) bug:
959 			 * http://milkytracker.org/docs/MilkyTracker.html#fxE6x
960 			 * roadblas.xm plays correctly with this. */
961 			if (flags & UF_FT2QUIRKS) mod->patbrk=mod->patpos;
962 		}
963 		break;
964 	case 0x7: /* set tremolo waveform */
965 		a->wavecontrol&=0x0f;
966 		a->wavecontrol|=nib<<4;
967 		break;
968 	case 0x8: /* set panning */
969 		if (mod->panflag) {
970 			if (nib<=8) nib<<=4;
971 			else nib*=17;
972 			a->main.panning=mod->panning[channel]=nib;
973 		}
974 		break;
975 	case 0x9: /* retrig note */
976 		/* do not retrigger on tick 0, until we are emulating FT2 and effect
977 		   data is zero */
978 		if (!tick && !((flags & UF_FT2QUIRKS) && (!nib)))
979 			break;
980 		/* only retrigger if data nibble > 0, or if tick 0 (FT2 compat) */
981 		if (nib || !tick) {
982 			if (!a->retrig) {
983 				/* when retrig counter reaches 0, reset counter and restart
984 				   the sample */
985 				if (a->main.period) a->main.kick=KICK_NOTE;
986 				a->retrig=nib;
987 			}
988 			a->retrig--; /* countdown */
989 		}
990 		break;
991 	case 0xa: /* fine volume slide up */
992 		if (tick)
993 			break;
994 		a->tmpvolume+=nib;
995 		if (a->tmpvolume>64) a->tmpvolume=64;
996 		break;
997 	case 0xb: /* fine volume slide dn  */
998 		if (tick)
999 			break;
1000 		a->tmpvolume-=nib;
1001 		if (a->tmpvolume<0)a->tmpvolume=0;
1002 		break;
1003 	case 0xc: /* cut note */
1004 		/* When tick reaches the cut-note value, turn the volume to
1005 		   zero (just like on the amiga) */
1006 		if (tick>=nib)
1007 			a->tmpvolume=0; /* just turn the volume down */
1008 		break;
1009 	case 0xd: /* note delay */
1010 		/* delay the start of the sample until tick==nib */
1011 		if (!tick)
1012 			a->main.notedelay=nib;
1013 		else if (a->main.notedelay)
1014 			a->main.notedelay--;
1015 		break;
1016 	case 0xe: /* pattern delay */
1017 		if (!tick)
1018 			if (!mod->patdly2)
1019 				mod->patdly=nib+1; /* only once, when tick=0 */
1020 		break;
1021 	case 0xf: /* invert loop, not supported  */
1022 		break;
1023 	}
1024 }
1025 
DoPTEffectE(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1026 static int DoPTEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1027 {
1028 	DoEEffects(tick, flags, a, mod, channel, UniGetByte());
1029 
1030 	return 0;
1031 }
1032 
DoPTEffectF(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1033 static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1034 {
1035 	UBYTE dat;
1036 
1037 	dat=UniGetByte();
1038 	if (tick||mod->patdly2) return 0;
1039 	if (mod->extspd&&(dat>=mod->bpmlimit))
1040 		mod->bpm=dat;
1041 	else
1042 	  if (dat) {
1043 		mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat;
1044 		mod->vbtick=0;
1045 	}
1046 
1047 	return 0;
1048 }
1049 
1050 /*========== Scream Tracker effects */
1051 
DoS3MEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1052 static int DoS3MEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1053 {
1054 	UBYTE speed;
1055 
1056 	speed = UniGetByte();
1057 
1058 	if (tick || mod->patdly2)
1059 		return 0;
1060 
1061 	if (speed > 128)
1062 		speed -= 128;
1063 	if (speed) {
1064 		mod->sngspd = speed;
1065 		mod->vbtick = 0;
1066 	}
1067 
1068 	return 0;
1069 }
1070 
DoS3MVolSlide(UWORD tick,UWORD flags,MP_CONTROL * a,UBYTE inf)1071 static void DoS3MVolSlide(UWORD tick, UWORD flags, MP_CONTROL *a, UBYTE inf)
1072 {
1073 	UBYTE lo, hi;
1074 
1075 	if (inf)
1076 		a->s3mvolslide=inf;
1077 	else
1078 		inf=a->s3mvolslide;
1079 
1080 	lo=inf&0xf;
1081 	hi=inf>>4;
1082 
1083 	if (!lo) {
1084 		if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume+=hi;
1085 	} else
1086 	  if (!hi) {
1087 		if ((tick)||(flags&UF_S3MSLIDES)) a->tmpvolume-=lo;
1088 	} else
1089 	  if (lo==0xf) {
1090 		if (!tick) a->tmpvolume+=(hi?hi:0xf);
1091 	} else
1092 	  if (hi==0xf) {
1093 		if (!tick) a->tmpvolume-=(lo?lo:0xf);
1094 	} else
1095 	  return;
1096 
1097 	if (a->tmpvolume<0)
1098 		a->tmpvolume=0;
1099 	else if (a->tmpvolume>64)
1100 		a->tmpvolume=64;
1101 }
1102 
DoS3MEffectD(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1103 static int DoS3MEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1104 {
1105 	DoS3MVolSlide(tick, flags, a, UniGetByte());
1106 
1107 	return 1;
1108 }
1109 
DoS3MSlideDn(UWORD tick,MP_CONTROL * a,UBYTE inf)1110 static void DoS3MSlideDn(UWORD tick, MP_CONTROL *a, UBYTE inf)
1111 {
1112 	UBYTE hi,lo;
1113 
1114 	if (inf)
1115 		a->slidespeed=inf;
1116 	else
1117 		inf=a->slidespeed;
1118 
1119 	hi=inf>>4;
1120 	lo=inf&0xf;
1121 
1122 	if (hi==0xf) {
1123 		if (!tick) a->tmpperiod+=(UWORD)lo<<2;
1124 	} else
1125 	  if (hi==0xe) {
1126 		if (!tick) a->tmpperiod+=lo;
1127 	} else {
1128 		if (tick) a->tmpperiod+=(UWORD)inf<<2;
1129 	}
1130 }
1131 
DoS3MEffectE(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1132 static int DoS3MEffectE(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1133 {
1134 	UBYTE dat;
1135 
1136 	dat=UniGetByte();
1137 	if (a->main.period)
1138 		DoS3MSlideDn(tick, a,dat);
1139 
1140 	return 0;
1141 }
1142 
DoS3MSlideUp(UWORD tick,MP_CONTROL * a,UBYTE inf)1143 static void DoS3MSlideUp(UWORD tick, MP_CONTROL *a, UBYTE inf)
1144 {
1145 	UBYTE hi,lo;
1146 
1147 	if (inf) a->slidespeed=inf;
1148 	else inf=a->slidespeed;
1149 
1150 	hi=inf>>4;
1151 	lo=inf&0xf;
1152 
1153 	if (hi==0xf) {
1154 		if (!tick) a->tmpperiod-=(UWORD)lo<<2;
1155 	} else
1156 	  if (hi==0xe) {
1157 		if (!tick) a->tmpperiod-=lo;
1158 	} else {
1159 		if (tick) a->tmpperiod-=(UWORD)inf<<2;
1160 	}
1161 }
1162 
DoS3MEffectF(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1163 static int DoS3MEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1164 {
1165 	UBYTE dat;
1166 
1167 	dat=UniGetByte();
1168 	if (a->main.period)
1169 		DoS3MSlideUp(tick, a,dat);
1170 
1171 	return 0;
1172 }
1173 
DoS3MEffectI(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1174 static int DoS3MEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1175 {
1176 	UBYTE inf, on, off;
1177 
1178 	inf = UniGetByte();
1179 	if (inf)
1180 		a->s3mtronof = inf;
1181 	else {
1182 		inf = a->s3mtronof;
1183 		if (!inf)
1184 			return 0;
1185 	}
1186 
1187 	if (!tick)
1188 		return 0;
1189 
1190 	on=(inf>>4)+1;
1191 	off=(inf&0xf)+1;
1192 	a->s3mtremor%=(on+off);
1193 	a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1194 	a->ownvol=1;
1195 	a->s3mtremor++;
1196 
1197 	return 0;
1198 }
1199 
DoS3MEffectQ(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1200 static int DoS3MEffectQ(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1201 {
1202 	UBYTE inf;
1203 
1204 	inf = UniGetByte();
1205 	if (a->main.period) {
1206 		if (inf) {
1207 			a->s3mrtgslide=inf>>4;
1208 			a->s3mrtgspeed=inf&0xf;
1209 		}
1210 
1211 		/* only retrigger if low nibble > 0 */
1212 		if (a->s3mrtgspeed>0) {
1213 			if (!a->retrig) {
1214 				/* when retrig counter reaches 0, reset counter and restart the
1215 				   sample */
1216 				if (a->main.kick!=KICK_NOTE) a->main.kick=KICK_KEYOFF;
1217 				a->retrig=a->s3mrtgspeed;
1218 
1219 				if ((tick)||(flags&UF_S3MSLIDES)) {
1220 					switch (a->s3mrtgslide) {
1221 					case 1:
1222 					case 2:
1223 					case 3:
1224 					case 4:
1225 					case 5:
1226 						a->tmpvolume-=(1<<(a->s3mrtgslide-1));
1227 						break;
1228 					case 6:
1229 						a->tmpvolume=(2*a->tmpvolume)/3;
1230 						break;
1231 					case 7:
1232 						a->tmpvolume>>=1;
1233 						break;
1234 					case 9:
1235 					case 0xa:
1236 					case 0xb:
1237 					case 0xc:
1238 					case 0xd:
1239 						a->tmpvolume+=(1<<(a->s3mrtgslide-9));
1240 						break;
1241 					case 0xe:
1242 						a->tmpvolume=(3*a->tmpvolume)>>1;
1243 						break;
1244 					case 0xf:
1245 						a->tmpvolume=a->tmpvolume<<1;
1246 						break;
1247 					}
1248 					if (a->tmpvolume<0)
1249 						a->tmpvolume=0;
1250 					else if (a->tmpvolume>64)
1251 						a->tmpvolume=64;
1252 				}
1253 			}
1254 			a->retrig--; /* countdown  */
1255 		}
1256 	}
1257 
1258 	return 0;
1259 }
1260 
DoS3MEffectR(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1261 static int DoS3MEffectR(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1262 {
1263 	UBYTE dat, q;
1264 	UWORD temp=0;	/* silence warning */
1265 
1266 	dat = UniGetByte();
1267 	if (!tick) {
1268 		if (dat&0x0f) a->trmdepth=dat&0xf;
1269 		if (dat&0xf0) a->trmspd=(dat&0xf0)>>2;
1270 	}
1271 
1272 	q=(a->trmpos>>2)&0x1f;
1273 
1274 	switch ((a->wavecontrol>>4)&3) {
1275 	case 0: /* sine */
1276 		temp=VibratoTable[q];
1277 		break;
1278 	case 1: /* ramp down */
1279 		q<<=3;
1280 		if (a->trmpos<0) q=255-q;
1281 		temp=q;
1282 		break;
1283 	case 2: /* square wave */
1284 		temp=255;
1285 		break;
1286 	case 3: /* random */
1287 		temp=getrandom(256);
1288 		break;
1289 	}
1290 
1291 	temp*=a->trmdepth;
1292 	temp>>=7;
1293 
1294 	if (a->trmpos>=0) {
1295 		a->volume=a->tmpvolume+temp;
1296 		if (a->volume>64) a->volume=64;
1297 	} else {
1298 		a->volume=a->tmpvolume-temp;
1299 		if (a->volume<0) a->volume=0;
1300 	}
1301 	a->ownvol = 1;
1302 
1303 	if (tick)
1304 		a->trmpos+=a->trmspd;
1305 
1306 	return 0;
1307 }
1308 
DoS3MEffectT(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1309 static int DoS3MEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1310 {
1311 	UBYTE tempo;
1312 
1313 	tempo = UniGetByte();
1314 
1315 	if (tick || mod->patdly2)
1316 		return 0;
1317 
1318 	mod->bpm = (tempo < 32) ? 32 : tempo;
1319 
1320 	return 0;
1321 }
1322 
DoS3MEffectU(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1323 static int DoS3MEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1324 {
1325 	UBYTE dat, q;
1326 	UWORD temp = 0;	/* silence warning */
1327 
1328 	dat = UniGetByte();
1329 	if (!tick) {
1330 		if (dat&0x0f) a->vibdepth=dat&0xf;
1331 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1332 	} else
1333 		if (a->main.period) {
1334 			q=(a->vibpos>>2)&0x1f;
1335 
1336 			switch (a->wavecontrol&3) {
1337 			case 0: /* sine */
1338 				temp=VibratoTable[q];
1339 				break;
1340 			case 1: /* ramp down */
1341 				q<<=3;
1342 				if (a->vibpos<0) q=255-q;
1343 				temp=q;
1344 				break;
1345 			case 2: /* square wave */
1346 				temp=255;
1347 				break;
1348 			case 3: /* random */
1349 				temp=getrandom(256);
1350 				break;
1351 			}
1352 
1353 			temp*=a->vibdepth;
1354 			temp>>=8;
1355 
1356 			if (a->vibpos>=0)
1357 				a->main.period=a->tmpperiod+temp;
1358 			else
1359 				a->main.period=a->tmpperiod-temp;
1360 			a->ownper = 1;
1361 
1362 			a->vibpos+=a->vibspd;
1363 	}
1364 
1365 	return 0;
1366 }
1367 
1368 /*========== Envelope helpers */
1369 
DoKeyOff(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1370 static int DoKeyOff(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1371 {
1372 	a->main.keyoff|=KEY_OFF;
1373 	if ((!(a->main.volflg&EF_ON))||(a->main.volflg&EF_LOOP))
1374 		a->main.keyoff=KEY_KILL;
1375 
1376 	return 0;
1377 }
1378 
DoKeyFade(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1379 static int DoKeyFade(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1380 {
1381 	UBYTE dat;
1382 
1383 	dat=UniGetByte();
1384 	if ((tick>=dat)||(tick==mod->sngspd-1)) {
1385 		a->main.keyoff=KEY_KILL;
1386 		if (!(a->main.volflg&EF_ON))
1387 			a->main.fadevol=0;
1388 	}
1389 
1390 	return 0;
1391 }
1392 
1393 /*========== Fast Tracker effects */
1394 
1395 /* DoXMEffect6 after DoXMEffectA */
1396 
DoXMEffectA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1397 static int DoXMEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1398 {
1399 	UBYTE inf, lo, hi;
1400 
1401 	inf = UniGetByte();
1402 	if (inf)
1403 		a->s3mvolslide = inf;
1404 	else
1405 		inf = a->s3mvolslide;
1406 
1407 	if (tick) {
1408 		lo=inf&0xf;
1409 		hi=inf>>4;
1410 
1411 		if (!hi) {
1412 			a->tmpvolume-=lo;
1413 			if (a->tmpvolume<0) a->tmpvolume=0;
1414 		} else {
1415 			a->tmpvolume+=hi;
1416 			if (a->tmpvolume>64) a->tmpvolume=64;
1417 		}
1418 	}
1419 
1420 	return 0;
1421 }
1422 
DoXMEffect6(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1423 static int DoXMEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1424 {
1425 	if (a->main.period)
1426 		DoVibrato(tick, a);
1427 
1428 	return DoXMEffectA(tick, flags, a, mod, channel);
1429 }
1430 
DoXMEffectE1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1431 static int DoXMEffectE1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1432 {
1433 	UBYTE dat;
1434 
1435 	dat=UniGetByte();
1436 	if (!tick) {
1437 		if (dat) a->fportupspd=dat;
1438 		if (a->main.period)
1439 			a->tmpperiod-=(a->fportupspd<<2);
1440 	}
1441 
1442 	return 0;
1443 }
1444 
DoXMEffectE2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1445 static int DoXMEffectE2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1446 {
1447 	UBYTE dat;
1448 
1449 	dat=UniGetByte();
1450 	if (!tick) {
1451 		if (dat) a->fportdnspd=dat;
1452 		if (a->main.period)
1453 			a->tmpperiod+=(a->fportdnspd<<2);
1454 	}
1455 
1456 	return 0;
1457 }
1458 
DoXMEffectEA(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1459 static int DoXMEffectEA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1460 {
1461 	UBYTE dat;
1462 
1463 	dat=UniGetByte();
1464 	if (!tick)
1465 		if (dat) a->fslideupspd=dat;
1466 	a->tmpvolume+=a->fslideupspd;
1467 	if (a->tmpvolume>64) a->tmpvolume=64;
1468 
1469 	return 0;
1470 }
1471 
DoXMEffectEB(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1472 static int DoXMEffectEB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1473 {
1474 	UBYTE dat;
1475 
1476 	dat=UniGetByte();
1477 	if (!tick)
1478 		if (dat) a->fslidednspd=dat;
1479 	a->tmpvolume-=a->fslidednspd;
1480 	if (a->tmpvolume<0) a->tmpvolume=0;
1481 
1482 	return 0;
1483 }
1484 
DoXMEffectG(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1485 static int DoXMEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1486 {
1487 	mod->volume=UniGetByte()<<1;
1488 	if (mod->volume>128) mod->volume=128;
1489 
1490 	return 0;
1491 }
1492 
DoXMEffectH(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1493 static int DoXMEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1494 {
1495 	UBYTE inf;
1496 
1497 	inf = UniGetByte();
1498 
1499 	if (tick) {
1500 		if (inf) mod->globalslide=inf;
1501 		else inf=mod->globalslide;
1502 		if (inf & 0xf0) inf&=0xf0;
1503 		mod->volume=mod->volume+((inf>>4)-(inf&0xf))*2;
1504 
1505 		if (mod->volume<0)
1506 			mod->volume=0;
1507 		else if (mod->volume>128)
1508 			mod->volume=128;
1509 	}
1510 
1511 	return 0;
1512 }
1513 
DoXMEffectL(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1514 static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1515 {
1516 	UBYTE dat;
1517 
1518 	dat=UniGetByte();
1519 	if ((!tick)&&(a->main.i)) {
1520 		UWORD points;
1521 		INSTRUMENT *i=a->main.i;
1522 		MP_VOICE *aout;
1523 
1524 		if ((aout=a->slave) != NULL) {
1525 			if (aout->venv.env) {
1526 				points=i->volenv[i->volpts-1].pos;
1527 				aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos;
1528 			}
1529 			if (aout->penv.env) {
1530 				points=i->panenv[i->panpts-1].pos;
1531 				aout->penv.p=aout->penv.env[(dat>points)?points:dat].pos;
1532 			}
1533 		}
1534 	}
1535 
1536 	return 0;
1537 }
1538 
DoXMEffectP(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1539 static int DoXMEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1540 {
1541 	UBYTE inf, lo, hi;
1542 	SWORD pan;
1543 
1544 	inf = UniGetByte();
1545 	if (!mod->panflag)
1546 		return 0;
1547 
1548 	if (inf)
1549 		a->pansspd = inf;
1550 	else
1551 		inf =a->pansspd;
1552 
1553 	if (tick) {
1554 		lo=inf&0xf;
1555 		hi=inf>>4;
1556 
1557 		/* slide right has absolute priority */
1558 		if (hi)
1559 			lo = 0;
1560 
1561 		pan=((a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning)+hi-lo;
1562 		a->main.panning=(pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1563 	}
1564 
1565 	return 0;
1566 }
1567 
DoXMEffectX1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1568 static int DoXMEffectX1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1569 {
1570 	UBYTE dat;
1571 
1572 	dat = UniGetByte();
1573 	if (dat)
1574 		a->ffportupspd = dat;
1575 	else
1576 		dat = a->ffportupspd;
1577 
1578 	if (a->main.period)
1579 		if (!tick) {
1580 			a->main.period-=dat;
1581 			a->tmpperiod-=dat;
1582 			a->ownper = 1;
1583 		}
1584 
1585 	return 0;
1586 }
1587 
DoXMEffectX2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1588 static int DoXMEffectX2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1589 {
1590 	UBYTE dat;
1591 
1592 	dat = UniGetByte();
1593 	if (dat)
1594 		a->ffportdnspd=dat;
1595 	else
1596 		dat = a->ffportdnspd;
1597 
1598 	if (a->main.period)
1599 		if (!tick) {
1600 			a->main.period+=dat;
1601 			a->tmpperiod+=dat;
1602 			a->ownper = 1;
1603 		}
1604 
1605 	return 0;
1606 }
1607 
1608 /*========== Impulse Tracker effects */
1609 
DoITToneSlide(UWORD tick,MP_CONTROL * a,UBYTE dat)1610 static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat)
1611 {
1612 	if (dat)
1613 		a->portspeed = dat;
1614 
1615 	/* if we don't come from another note, ignore the slide and play the note
1616 	   as is */
1617 	if (!a->oldnote || !a->main.period)
1618 		return;
1619 
1620 	if ((!tick)&&(a->newsamp)){
1621 		a->main.kick=KICK_NOTE;
1622 		a->main.start=-1;
1623 	} else
1624 		a->main.kick=(a->main.kick==KICK_NOTE)?KICK_ENV:KICK_ABSENT;
1625 
1626 	if (tick) {
1627 		int dist;
1628 
1629 		/* We have to slide a->main.period towards a->wantedperiod, compute the
1630 		   difference between those two values */
1631 		dist=a->main.period-a->wantedperiod;
1632 
1633 		/* if they are equal or if portamentospeed is too big... */
1634 		if ((!dist)||((a->portspeed<<2)>abs(dist)))
1635 			/* ... make tmpperiod equal tperiod */
1636 			a->tmpperiod=a->main.period=a->wantedperiod;
1637 		else
1638 		  if (dist>0) {
1639 			a->tmpperiod-=a->portspeed<<2;
1640 			a->main.period-=a->portspeed<<2; /* dist>0 slide up */
1641 		} else {
1642 			a->tmpperiod+=a->portspeed<<2;
1643 			a->main.period+=a->portspeed<<2; /* dist<0 slide down */
1644 		}
1645 	} else
1646 		a->tmpperiod=a->main.period;
1647 	a->ownper=1;
1648 }
1649 
DoITEffectG(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1650 static int DoITEffectG(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1651 {
1652 	DoITToneSlide(tick, a, UniGetByte());
1653 
1654 	return 0;
1655 }
1656 
DoITVibrato(UWORD tick,MP_CONTROL * a,UBYTE dat)1657 static void DoITVibrato(UWORD tick, MP_CONTROL *a, UBYTE dat)
1658 {
1659 	UBYTE q;
1660 	UWORD temp=0;
1661 
1662 	if (!tick) {
1663 		if (dat&0x0f) a->vibdepth=dat&0xf;
1664 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1665 	}
1666 	if (!a->main.period)
1667 		return;
1668 
1669 	q=(a->vibpos>>2)&0x1f;
1670 
1671 	switch (a->wavecontrol&3) {
1672 	case 0: /* sine */
1673 		temp=VibratoTable[q];
1674 		break;
1675 	case 1: /* square wave */
1676 		temp=255;
1677 		break;
1678 	case 2: /* ramp down */
1679 		q<<=3;
1680 		if (a->vibpos<0) q=255-q;
1681 		temp=q;
1682 		break;
1683 	case 3: /* random */
1684 		temp=getrandom(256);
1685 		break;
1686 	}
1687 
1688 	temp*=a->vibdepth;
1689 	temp>>=8;
1690 	temp<<=2;
1691 
1692 	if (a->vibpos>=0)
1693 		a->main.period=a->tmpperiod+temp;
1694 	else
1695 		a->main.period=a->tmpperiod-temp;
1696 	a->ownper=1;
1697 
1698 	a->vibpos+=a->vibspd;
1699 }
1700 
DoITEffectH(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1701 static int DoITEffectH(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1702 {
1703 	DoITVibrato(tick, a, UniGetByte());
1704 
1705 	return 0;
1706 }
1707 
DoITEffectI(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1708 static int DoITEffectI(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1709 {
1710 	UBYTE inf, on, off;
1711 
1712 	inf = UniGetByte();
1713 	if (inf)
1714 		a->s3mtronof = inf;
1715 	else {
1716 		inf = a->s3mtronof;
1717 		if (!inf)
1718 			return 0;
1719 	}
1720 
1721 	on=(inf>>4);
1722 	off=(inf&0xf);
1723 
1724 	a->s3mtremor%=(on+off);
1725 	a->volume=(a->s3mtremor<on)?a->tmpvolume:0;
1726 	a->ownvol = 1;
1727 	a->s3mtremor++;
1728 
1729 	return 0;
1730 }
1731 
DoITEffectM(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1732 static int DoITEffectM(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1733 {
1734 	a->main.chanvol=UniGetByte();
1735 	if (a->main.chanvol>64)
1736 		a->main.chanvol=64;
1737 	else if (a->main.chanvol<0)
1738 		a->main.chanvol=0;
1739 
1740 	return 0;
1741 }
1742 
DoITEffectN(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1743 static int DoITEffectN(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1744 {
1745 	UBYTE inf, lo, hi;
1746 
1747 	inf = UniGetByte();
1748 
1749 	if (inf)
1750 		a->chanvolslide = inf;
1751 	else
1752 		inf = a->chanvolslide;
1753 
1754 	lo=inf&0xf;
1755 	hi=inf>>4;
1756 
1757 	if (!hi)
1758 		a->main.chanvol-=lo;
1759 	else
1760 	  if (!lo) {
1761 		a->main.chanvol+=hi;
1762 	} else
1763 	  if (hi==0xf) {
1764 		if (!tick) a->main.chanvol-=lo;
1765 	} else
1766 	  if (lo==0xf) {
1767 		if (!tick) a->main.chanvol+=hi;
1768 	}
1769 
1770 	if (a->main.chanvol<0)
1771 		a->main.chanvol=0;
1772 	else if (a->main.chanvol>64)
1773 		a->main.chanvol=64;
1774 
1775 	return 0;
1776 }
1777 
DoITEffectP(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1778 static int DoITEffectP(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1779 {
1780 	UBYTE inf, lo, hi;
1781 	SWORD pan;
1782 
1783 	inf = UniGetByte();
1784 	if (inf)
1785 		a->pansspd = inf;
1786 	else
1787 		inf = a->pansspd;
1788 
1789 	if (!mod->panflag)
1790 		return 0;
1791 
1792 	lo=inf&0xf;
1793 	hi=inf>>4;
1794 
1795 	pan=(a->main.panning==PAN_SURROUND)?PAN_CENTER:a->main.panning;
1796 
1797 	if (!hi)
1798 		pan+=lo<<2;
1799 	else
1800 	  if (!lo) {
1801 		pan-=hi<<2;
1802 	} else
1803 	  if (hi==0xf) {
1804 		if (!tick) pan+=lo<<2;
1805 	} else
1806 	  if (lo==0xf) {
1807 		if (!tick) pan-=hi<<2;
1808 	}
1809 	a->main.panning=
1810 	  (pan<PAN_LEFT)?PAN_LEFT:(pan>PAN_RIGHT?PAN_RIGHT:pan);
1811 
1812 	return 0;
1813 }
1814 
DoITEffectT(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1815 static int DoITEffectT(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1816 {
1817 	UBYTE tempo;
1818 	SWORD temp;
1819 
1820 	tempo = UniGetByte();
1821 
1822 	if (mod->patdly2)
1823 		return 0;
1824 
1825 	temp = mod->bpm;
1826 	if (tempo & 0x10)
1827 		temp += (tempo & 0x0f);
1828 	else
1829 		temp -= tempo;
1830 
1831 	mod->bpm=(temp>255)?255:(temp<1?1:temp);
1832 
1833 	return 0;
1834 }
1835 
DoITEffectU(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1836 static int DoITEffectU(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1837 {
1838 	UBYTE dat, q;
1839 	UWORD temp = 0;	/* silence warning */
1840 
1841 	dat = UniGetByte();
1842 	if (!tick) {
1843 		if (dat&0x0f) a->vibdepth=dat&0xf;
1844 		if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1845 	}
1846 	if (a->main.period) {
1847 		q=(a->vibpos>>2)&0x1f;
1848 
1849 		switch (a->wavecontrol&3) {
1850 		case 0: /* sine */
1851 			temp=VibratoTable[q];
1852 			break;
1853 		case 1: /* square wave */
1854 			temp=255;
1855 			break;
1856 		case 2: /* ramp down */
1857 			q<<=3;
1858 			if (a->vibpos<0) q=255-q;
1859 			temp=q;
1860 			break;
1861 		case 3: /* random */
1862 			temp=getrandom(256);
1863 			break;
1864 		}
1865 
1866 		temp*=a->vibdepth;
1867 		temp>>=8;
1868 
1869 		if (a->vibpos>=0)
1870 			a->main.period=a->tmpperiod+temp;
1871 		else
1872 			a->main.period=a->tmpperiod-temp;
1873 		a->ownper = 1;
1874 
1875 		a->vibpos+=a->vibspd;
1876 	}
1877 
1878 	return 0;
1879 }
1880 
DoITEffectW(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1881 static int DoITEffectW(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1882 {
1883 	UBYTE inf, lo, hi;
1884 
1885 	inf = UniGetByte();
1886 
1887 	if (inf)
1888 		mod->globalslide = inf;
1889 	else
1890 		inf = mod->globalslide;
1891 
1892 	lo=inf&0xf;
1893 	hi=inf>>4;
1894 
1895 	if (!lo) {
1896 		if (tick) mod->volume+=hi;
1897 	} else
1898 	  if (!hi) {
1899 		if (tick) mod->volume-=lo;
1900 	} else
1901 	  if (lo==0xf) {
1902 		if (!tick) mod->volume+=hi;
1903 	} else
1904 	  if (hi==0xf) {
1905 		if (!tick) mod->volume-=lo;
1906 	}
1907 
1908 	if (mod->volume<0)
1909 		mod->volume=0;
1910 	else if (mod->volume>128)
1911 		mod->volume=128;
1912 
1913 	return 0;
1914 }
1915 
DoITEffectY(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1916 static int DoITEffectY(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1917 {
1918 	UBYTE dat, q;
1919 	SLONG temp = 0;	/* silence warning */
1920 
1921 
1922 	dat=UniGetByte();
1923 	if (!tick) {
1924 		if (dat&0x0f) a->panbdepth=(dat&0xf);
1925 		if (dat&0xf0) a->panbspd=(dat&0xf0)>>4;
1926 	}
1927 	if (mod->panflag) {
1928 		q=a->panbpos;
1929 
1930 		switch (a->panbwave) {
1931 		case 0: /* sine */
1932 			temp=PanbrelloTable[q];
1933 			break;
1934 		case 1: /* square wave */
1935 			temp=(q<0x80)?64:0;
1936 			break;
1937 		case 2: /* ramp down */
1938 			q<<=3;
1939 			temp=q;
1940 			break;
1941 		case 3: /* random */
1942 			temp=getrandom(256);
1943 			break;
1944 		}
1945 
1946 		temp*=a->panbdepth;
1947 		temp=(temp/8)+mod->panning[channel];
1948 
1949 		a->main.panning=
1950 			(temp<PAN_LEFT)?PAN_LEFT:(temp>PAN_RIGHT?PAN_RIGHT:temp);
1951 		a->panbpos+=a->panbspd;
1952 
1953 	}
1954 
1955 	return 0;
1956 }
1957 
1958 static void DoNNAEffects(MODULE *, MP_CONTROL *, UBYTE);
1959 
1960 /* Impulse/Scream Tracker Sxx effects.
1961    All Sxx effects share the same memory space. */
DoITEffectS0(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)1962 static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
1963 {
1964 	UBYTE dat, inf, c;
1965 
1966 	dat = UniGetByte();
1967 	inf=dat&0xf;
1968 	c=dat>>4;
1969 
1970 	if (!dat) {
1971 		c=a->sseffect;
1972 		inf=a->ssdata;
1973 	} else {
1974 		a->sseffect=c;
1975 		a->ssdata=inf;
1976 	}
1977 
1978 	switch (c) {
1979 	case SS_GLISSANDO: /* S1x set glissando voice */
1980 		DoEEffects(tick, flags, a, mod, channel, 0x30|inf);
1981 		break;
1982 	case SS_FINETUNE: /* S2x set finetune */
1983 		DoEEffects(tick, flags, a, mod, channel, 0x50|inf);
1984 		break;
1985 	case SS_VIBWAVE: /* S3x set vibrato waveform */
1986 		DoEEffects(tick, flags, a, mod, channel, 0x40|inf);
1987 		break;
1988 	case SS_TREMWAVE: /* S4x set tremolo waveform */
1989 		DoEEffects(tick, flags, a, mod, channel, 0x70|inf);
1990 		break;
1991 	case SS_PANWAVE: /* S5x panbrello */
1992 		a->panbwave=inf;
1993 		break;
1994 	case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */
1995 		DoEEffects(tick, flags, a, mod, channel, 0xe0|inf);
1996 		break;
1997 	case SS_S7EFFECTS: /* S7x instrument / NNA commands */
1998 		DoNNAEffects(mod, a, inf);
1999 		break;
2000 	case SS_PANNING: /* S8x set panning position */
2001 		DoEEffects(tick, flags, a, mod, channel, 0x80 | inf);
2002 		break;
2003 	case SS_SURROUND: /* S9x set surround sound */
2004 		if (mod->panflag)
2005 			a->main.panning = mod->panning[channel] = PAN_SURROUND;
2006 		break;
2007 	case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
2008 		if (!tick) {
2009 			a->hioffset=inf<<16;
2010 			a->main.start=a->hioffset|a->soffset;
2011 
2012 			if ((a->main.s)&&(a->main.start>a->main.s->length))
2013 				a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2014 				    a->main.s->loopstart:a->main.s->length;
2015 		}
2016 		break;
2017 	case SS_PATLOOP: /* SBx pattern loop */
2018 		DoEEffects(tick, flags, a, mod, channel, 0x60|inf);
2019 		break;
2020 	case SS_NOTECUT: /* SCx notecut */
2021 		if (!inf) inf = 1;
2022 		DoEEffects(tick, flags, a, mod, channel, 0xC0|inf);
2023 		break;
2024 	case SS_NOTEDELAY: /* SDx notedelay */
2025 		DoEEffects(tick, flags, a, mod, channel, 0xD0|inf);
2026 		break;
2027 	case SS_PATDELAY: /* SEx patterndelay */
2028 		DoEEffects(tick, flags, a, mod, channel, 0xE0|inf);
2029 		break;
2030 	}
2031 
2032 	return 0;
2033 }
2034 
2035 /*========== Impulse Tracker Volume/Pan Column effects */
2036 
2037 /*
2038  * All volume/pan column effects share the same memory space.
2039  */
2040 
DoVolEffects(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2041 static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2042 {
2043 	UBYTE c, inf;
2044 
2045 	c = UniGetByte();
2046 	inf = UniGetByte();
2047 
2048 	if ((!c)&&(!inf)) {
2049 		c=a->voleffect;
2050 		inf=a->voldata;
2051 	} else {
2052 		a->voleffect=c;
2053 		a->voldata=inf;
2054 	}
2055 
2056 	if (c)
2057 		switch (c) {
2058 		case VOL_VOLUME:
2059 			if (tick) break;
2060 			if (inf>64) inf=64;
2061 			a->tmpvolume=inf;
2062 			break;
2063 		case VOL_PANNING:
2064 			if (mod->panflag)
2065 				a->main.panning=inf;
2066 			break;
2067 		case VOL_VOLSLIDE:
2068 			DoS3MVolSlide(tick, flags, a, inf);
2069 			return 1;
2070 		case VOL_PITCHSLIDEDN:
2071 			if (a->main.period)
2072 				DoS3MSlideDn(tick, a, inf);
2073 			break;
2074 		case VOL_PITCHSLIDEUP:
2075 			if (a->main.period)
2076 				DoS3MSlideUp(tick, a, inf);
2077 			break;
2078 		case VOL_PORTAMENTO:
2079 			DoITToneSlide(tick, a, inf);
2080 			break;
2081 		case VOL_VIBRATO:
2082 			DoITVibrato(tick, a, inf);
2083 			break;
2084 	}
2085 
2086 	return 0;
2087 }
2088 
2089 /*========== UltraTracker effects */
2090 
DoULTEffect9(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2091 static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2092 {
2093 	UWORD offset=UniGetWord();
2094 
2095 	if (offset)
2096 		a->ultoffset=offset;
2097 
2098 	a->main.start=a->ultoffset<<2;
2099 	if ((a->main.s)&&(a->main.start>a->main.s->length))
2100 		a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2101 		    a->main.s->loopstart:a->main.s->length;
2102 
2103 	return 0;
2104 }
2105 
2106 /*========== OctaMED effects */
2107 
DoMEDSpeed(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2108 static int DoMEDSpeed(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2109 {
2110 	UWORD speed=UniGetWord();
2111 
2112 	mod->bpm=speed;
2113 
2114 	return 0;
2115 }
2116 
DoMEDEffectF1(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2117 static int DoMEDEffectF1(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2118 {
2119 	DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/2));
2120 
2121 	return 0;
2122 }
2123 
DoMEDEffectF2(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2124 static int DoMEDEffectF2(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2125 {
2126 	DoEEffects(tick, flags, a, mod, channel, 0xd0|(mod->sngspd/2));
2127 
2128 	return 0;
2129 }
2130 
DoMEDEffectF3(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2131 static int DoMEDEffectF3(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2132 {
2133 	DoEEffects(tick, flags, a, mod, channel, 0x90|(mod->sngspd/3));
2134 
2135 	return 0;
2136 }
2137 
2138 /*========== Oktalyzer effects */
2139 
DoOktArp(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2140 static int DoOktArp(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2141 {
2142 	UBYTE dat, dat2;
2143 
2144 	dat2 = UniGetByte();	/* arpeggio style */
2145 	dat = UniGetByte();
2146 	if (!tick) {
2147 		if (!dat && (flags & UF_ARPMEM))
2148 			dat=a->arpmem;
2149 		else
2150 			a->arpmem=dat;
2151 	}
2152 	if (a->main.period)
2153 		DoArpeggio(tick, flags, a, dat2);
2154 
2155 	return 0;
2156 }
2157 
2158 /*========== General player functions */
2159 
DoNothing(UWORD tick,UWORD flags,MP_CONTROL * a,MODULE * mod,SWORD channel)2160 static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2161 {
2162 	UniSkipOpcode();
2163 
2164 	return 0;
2165 }
2166 
2167 typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD);
2168 
2169 static effect_func effects[UNI_LAST] = {
2170 	DoNothing,		/* 0 */
2171 	DoNothing,		/* UNI_NOTE */
2172 	DoNothing,		/* UNI_INSTRUMENT */
2173 	DoPTEffect0,	/* UNI_PTEFFECT0 */
2174 	DoPTEffect1,	/* UNI_PTEFFECT1 */
2175 	DoPTEffect2,	/* UNI_PTEFFECT2 */
2176 	DoPTEffect3,	/* UNI_PTEFFECT3 */
2177 	DoPTEffect4,	/* UNI_PTEFFECT4 */
2178 	DoPTEffect5,	/* UNI_PTEFFECT5 */
2179 	DoPTEffect6,	/* UNI_PTEFFECT6 */
2180 	DoPTEffect7,	/* UNI_PTEFFECT7 */
2181 	DoPTEffect8,	/* UNI_PTEFFECT8 */
2182 	DoPTEffect9,	/* UNI_PTEFFECT9 */
2183 	DoPTEffectA,	/* UNI_PTEFFECTA */
2184 	DoPTEffectB,	/* UNI_PTEFFECTB */
2185 	DoPTEffectC,	/* UNI_PTEFFECTC */
2186 	DoPTEffectD,	/* UNI_PTEFFECTD */
2187 	DoPTEffectE,	/* UNI_PTEFFECTE */
2188 	DoPTEffectF,	/* UNI_PTEFFECTF */
2189 	DoS3MEffectA,	/* UNI_S3MEFFECTA */
2190 	DoS3MEffectD,	/* UNI_S3MEFFECTD */
2191 	DoS3MEffectE,	/* UNI_S3MEFFECTE */
2192 	DoS3MEffectF,	/* UNI_S3MEFFECTF */
2193 	DoS3MEffectI,	/* UNI_S3MEFFECTI */
2194 	DoS3MEffectQ,	/* UNI_S3MEFFECTQ */
2195 	DoS3MEffectR,	/* UNI_S3MEFFECTR */
2196 	DoS3MEffectT,	/* UNI_S3MEFFECTT */
2197 	DoS3MEffectU,	/* UNI_S3MEFFECTU */
2198 	DoKeyOff,	/* UNI_KEYOFF */
2199 	DoKeyFade,	/* UNI_KEYFADE */
2200 	DoVolEffects,	/* UNI_VOLEFFECTS */
2201 	DoPTEffect4,	/* UNI_XMEFFECT4 */
2202 	DoXMEffect6,	/* UNI_XMEFFECT6 */
2203 	DoXMEffectA,	/* UNI_XMEFFECTA */
2204 	DoXMEffectE1,	/* UNI_XMEFFECTE1 */
2205 	DoXMEffectE2,	/* UNI_XMEFFECTE2 */
2206 	DoXMEffectEA,	/* UNI_XMEFFECTEA */
2207 	DoXMEffectEB,	/* UNI_XMEFFECTEB */
2208 	DoXMEffectG,	/* UNI_XMEFFECTG */
2209 	DoXMEffectH,	/* UNI_XMEFFECTH */
2210 	DoXMEffectL,	/* UNI_XMEFFECTL */
2211 	DoXMEffectP,	/* UNI_XMEFFECTP */
2212 	DoXMEffectX1,	/* UNI_XMEFFECTX1 */
2213 	DoXMEffectX2,	/* UNI_XMEFFECTX2 */
2214 	DoITEffectG,	/* UNI_ITEFFECTG */
2215 	DoITEffectH,	/* UNI_ITEFFECTH */
2216 	DoITEffectI,	/* UNI_ITEFFECTI */
2217 	DoITEffectM,	/* UNI_ITEFFECTM */
2218 	DoITEffectN,	/* UNI_ITEFFECTN */
2219 	DoITEffectP,	/* UNI_ITEFFECTP */
2220 	DoITEffectT,	/* UNI_ITEFFECTT */
2221 	DoITEffectU,	/* UNI_ITEFFECTU */
2222 	DoITEffectW,	/* UNI_ITEFFECTW */
2223 	DoITEffectY,	/* UNI_ITEFFECTY */
2224 	DoNothing,	/* UNI_ITEFFECTZ */
2225 	DoITEffectS0,	/* UNI_ITEFFECTS0 */
2226 	DoULTEffect9,	/* UNI_ULTEFFECT9 */
2227 	DoMEDSpeed,	/* UNI_MEDSPEED */
2228 	DoMEDEffectF1,	/* UNI_MEDEFFECTF1 */
2229 	DoMEDEffectF2,	/* UNI_MEDEFFECTF2 */
2230 	DoMEDEffectF3,	/* UNI_MEDEFFECTF3 */
2231 	DoOktArp,	/* UNI_OKTARP */
2232 };
2233 
pt_playeffects(MODULE * mod,SWORD channel,MP_CONTROL * a)2234 static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
2235 {
2236 	UWORD tick = mod->vbtick;
2237 	UWORD flags = mod->flags;
2238 	UBYTE c;
2239 	int explicitslides = 0;
2240 	effect_func f;
2241 
2242 	while((c=UniGetByte()) != 0) {
2243 #if 0 /* this doesn't normally happen unless things go fubar elsewhere */
2244 		if (c >= UNI_LAST)
2245 		    fprintf(stderr,"fubar'ed opcode %u\n",c);
2246 #endif
2247 		f = effects[c];
2248 		if (f != DoNothing)
2249 		    a->sliding = 0;
2250 		explicitslides |= f(tick, flags, a, mod, channel);
2251 	}
2252 	return explicitslides;
2253 }
2254 
DoNNAEffects(MODULE * mod,MP_CONTROL * a,UBYTE dat)2255 static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2256 {
2257 	int t;
2258 	MP_VOICE *aout;
2259 
2260 	dat&=0xf;
2261 	aout=(a->slave)?a->slave:NULL;
2262 
2263 	switch (dat) {
2264 	case 0x0: /* past note cut */
2265 		for (t=0;t<NUMVOICES(mod);t++)
2266 			if (mod->voice[t].master==a)
2267 				mod->voice[t].main.fadevol=0;
2268 		break;
2269 	case 0x1: /* past note off */
2270 		for (t=0;t<NUMVOICES(mod);t++)
2271 			if (mod->voice[t].master==a) {
2272 				mod->voice[t].main.keyoff|=KEY_OFF;
2273 				if ((!(mod->voice[t].venv.flg & EF_ON))||
2274 				   (mod->voice[t].venv.flg & EF_LOOP))
2275 					mod->voice[t].main.keyoff=KEY_KILL;
2276 			}
2277 		break;
2278 	case 0x2: /* past note fade */
2279 		for (t=0;t<NUMVOICES(mod);t++)
2280 			if (mod->voice[t].master==a)
2281 				mod->voice[t].main.keyoff|=KEY_FADE;
2282 		break;
2283 	case 0x3: /* set NNA note cut */
2284 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CUT;
2285 		break;
2286 	case 0x4: /* set NNA note continue */
2287 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_CONTINUE;
2288 		break;
2289 	case 0x5: /* set NNA note off */
2290 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF;
2291 		break;
2292 	case 0x6: /* set NNA note fade */
2293 		a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE;
2294 		break;
2295 	case 0x7: /* disable volume envelope */
2296 		if (aout)
2297 			aout->main.volflg&=~EF_ON;
2298 		break;
2299 	case 0x8: /* enable volume envelope  */
2300 		if (aout)
2301 			aout->main.volflg|=EF_ON;
2302 		break;
2303 	case 0x9: /* disable panning envelope */
2304 		if (aout)
2305 			aout->main.panflg&=~EF_ON;
2306 		break;
2307 	case 0xa: /* enable panning envelope */
2308 		if (aout)
2309 			aout->main.panflg|=EF_ON;
2310 		break;
2311 	case 0xb: /* disable pitch envelope */
2312 		if (aout)
2313 			aout->main.pitflg&=~EF_ON;
2314 		break;
2315 	case 0xc: /* enable pitch envelope */
2316 		if (aout)
2317 			aout->main.pitflg|=EF_ON;
2318 		break;
2319 	}
2320 }
2321 
pt_UpdateVoices(MODULE * mod,int max_volume)2322 static void pt_UpdateVoices(MODULE *mod, int max_volume)
2323 {
2324 	SWORD envpan,envvol,envpit,channel;
2325 	UWORD playperiod;
2326 	SLONG vibval,vibdpt;
2327 	ULONG tmpvol;
2328 
2329 	MP_VOICE *aout;
2330 	INSTRUMENT *i;
2331 	SAMPLE *s;
2332 
2333 	mod->totalchn=mod->realchn=0;
2334 	for (channel=0;channel<NUMVOICES(mod);channel++) {
2335 		aout=&mod->voice[channel];
2336 		i=aout->main.i;
2337 		s=aout->main.s;
2338 
2339 		if (!s || !s->length) continue;
2340 
2341 		if (aout->main.period<40)
2342 			aout->main.period=40;
2343 		else if (aout->main.period>50000)
2344 			aout->main.period=50000;
2345 
2346 		if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) {
2347 			Voice_Play_internal(channel,s,(aout->main.start==-1)?
2348 			    ((s->flags&SF_UST_LOOP)?s->loopstart:0):aout->main.start);
2349 			aout->main.fadevol=32768;
2350 			aout->aswppos=0;
2351 		}
2352 
2353 		envvol = 256;
2354 		envpan = PAN_CENTER;
2355 		envpit = 32;
2356 		if (i && ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_ENV))) {
2357 			if (aout->main.volflg & EF_ON)
2358 				envvol = StartEnvelope(&aout->venv,aout->main.volflg,
2359 				  i->volpts,i->volsusbeg,i->volsusend,
2360 				  i->volbeg,i->volend,i->volenv,aout->main.keyoff);
2361 			if (aout->main.panflg & EF_ON)
2362 				envpan = StartEnvelope(&aout->penv,aout->main.panflg,
2363 				  i->panpts,i->pansusbeg,i->pansusend,
2364 				  i->panbeg,i->panend,i->panenv,aout->main.keyoff);
2365 			if (aout->main.pitflg & EF_ON)
2366 				envpit = StartEnvelope(&aout->cenv,aout->main.pitflg,
2367 				  i->pitpts,i->pitsusbeg,i->pitsusend,
2368 				  i->pitbeg,i->pitend,i->pitenv,aout->main.keyoff);
2369 
2370 			if (aout->cenv.flg & EF_ON)
2371 				aout->masterperiod=GetPeriod(mod->flags,
2372 				  (UWORD)aout->main.note<<1, aout->master->speed);
2373 		} else {
2374 			if (aout->main.volflg & EF_ON)
2375 				envvol = ProcessEnvelope(aout,&aout->venv,256);
2376 			if (aout->main.panflg & EF_ON)
2377 				envpan = ProcessEnvelope(aout,&aout->penv,PAN_CENTER);
2378 			if (aout->main.pitflg & EF_ON)
2379 				envpit = ProcessEnvelope(aout,&aout->cenv,32);
2380 		}
2381 		if (aout->main.kick == KICK_NOTE) {
2382 			aout->main.kick_flag = 1;
2383 		}
2384 		aout->main.kick=KICK_ABSENT;
2385 
2386 		tmpvol = aout->main.fadevol;	/* max 32768 */
2387 		tmpvol *= aout->main.chanvol;	/* * max 64 */
2388 		tmpvol *= aout->main.outvolume;	/* * max 256 */
2389 		tmpvol /= (256 * 64);			/* tmpvol is max 32768 again */
2390 		aout->totalvol = tmpvol >> 2;	/* used to determine samplevolume */
2391 		tmpvol *= envvol;				/* * max 256 */
2392 		tmpvol *= mod->volume;			/* * max 128 */
2393 		tmpvol /= (128 * 256 * 128);
2394 
2395 		/* fade out */
2396 		if (mod->sngpos>=mod->numpos)
2397 			tmpvol=0;
2398 		else
2399 			tmpvol=(tmpvol*max_volume)/128;
2400 
2401 		if ((aout->masterchn!=-1)&& mod->control[aout->masterchn].muted)
2402 			Voice_SetVolume_internal(channel,0);
2403 		else {
2404 			Voice_SetVolume_internal(channel,tmpvol);
2405 			if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2406 				mod->realchn++;
2407 			mod->totalchn++;
2408 		}
2409 
2410 		if (aout->main.panning==PAN_SURROUND)
2411 			Voice_SetPanning_internal(channel,PAN_SURROUND);
2412 		else
2413 			if ((mod->panflag)&&(aout->penv.flg & EF_ON))
2414 				Voice_SetPanning_internal(channel,
2415 				    DoPan(envpan,aout->main.panning));
2416 			else
2417 				Voice_SetPanning_internal(channel,aout->main.panning);
2418 
2419 		if (aout->main.period && s->vibdepth)
2420 			switch (s->vibtype) {
2421 			case 0:
2422 				vibval=avibtab[s->avibpos&127];
2423 				if (aout->avibpos & 0x80) vibval=-vibval;
2424 				break;
2425 			case 1:
2426 				vibval=64;
2427 				if (aout->avibpos & 0x80) vibval=-vibval;
2428 				break;
2429 			case 2:
2430 				vibval=63-(((aout->avibpos+128)&255)>>1);
2431 				break;
2432 			default:
2433 				vibval=(((aout->avibpos+128)&255)>>1)-64;
2434 				break;
2435 			}
2436 		else
2437 			vibval=0;
2438 
2439 		if (s->vibflags & AV_IT) {
2440 			if ((aout->aswppos>>8)<s->vibdepth) {
2441 				aout->aswppos += s->vibsweep;
2442 				vibdpt=aout->aswppos;
2443 			} else
2444 				vibdpt=s->vibdepth<<8;
2445 			vibval=(vibval*vibdpt)>>16;
2446 			if (aout->mflag) {
2447 				if (!(mod->flags&UF_LINEAR)) vibval>>=1;
2448 				aout->main.period-=vibval;
2449 			}
2450 		} else {
2451 			/* do XM style auto-vibrato */
2452 			if (!(aout->main.keyoff & KEY_OFF)) {
2453 				if (aout->aswppos<s->vibsweep) {
2454 					vibdpt=(aout->aswppos*s->vibdepth)/s->vibsweep;
2455 					aout->aswppos++;
2456 				} else
2457 					vibdpt=s->vibdepth;
2458 			} else {
2459 				/* keyoff -> depth becomes 0 if final depth wasn't reached or
2460 				   stays at final level if depth WAS reached */
2461 				if (aout->aswppos>=s->vibsweep)
2462 					vibdpt=s->vibdepth;
2463 				else
2464 					vibdpt=0;
2465 			}
2466 			vibval=(vibval*vibdpt)>>8;
2467 			aout->main.period-=vibval;
2468 		}
2469 
2470 		/* update vibrato position */
2471 		aout->avibpos=(aout->avibpos+s->vibrate)&0xff;
2472 
2473 		/* process pitch envelope */
2474 		playperiod=aout->main.period;
2475 
2476 		if ((aout->main.pitflg&EF_ON)&&(envpit!=32)) {
2477 			long p1;
2478 
2479 			envpit-=32;
2480 			if ((aout->main.note<<1)+envpit<=0) envpit=-(aout->main.note<<1);
2481 
2482 			p1=GetPeriod(mod->flags, ((UWORD)aout->main.note<<1)+envpit,
2483 			    aout->master->speed)-aout->masterperiod;
2484 			if (p1>0) {
2485 				if ((UWORD)(playperiod+p1)<=playperiod) {
2486 					p1=0;
2487 					aout->main.keyoff|=KEY_OFF;
2488 				}
2489 			} else if (p1<0) {
2490 				if ((UWORD)(playperiod+p1)>=playperiod) {
2491 					p1=0;
2492 					aout->main.keyoff|=KEY_OFF;
2493 				}
2494 			}
2495 			playperiod+=p1;
2496 		}
2497 
2498 		if (!aout->main.fadevol) { /* check for a dead note (fadevol=0) */
2499 			Voice_Stop_internal(channel);
2500 			mod->totalchn--;
2501 			if ((tmpvol)&&(aout->master)&&(aout->master->slave==aout))
2502 				mod->realchn--;
2503 		} else {
2504 			Voice_SetFrequency_internal(channel,
2505 			                            getfrequency(mod->flags,playperiod));
2506 
2507 			/* if keyfade, start substracting fadeoutspeed from fadevol: */
2508 			if ((i)&&(aout->main.keyoff&KEY_FADE)) {
2509 				if (aout->main.fadevol>=i->volfade)
2510 					aout->main.fadevol-=i->volfade;
2511 				else
2512 					aout->main.fadevol=0;
2513 			}
2514 		}
2515 
2516 		md_bpm=mod->bpm+mod->relspd;
2517 		if (md_bpm<32)
2518 			md_bpm=32;
2519 		else if ((!(mod->flags&UF_HIGHBPM)) && md_bpm>255)
2520 			md_bpm=255;
2521 	}
2522 }
2523 
2524 /* Handles new notes or instruments */
pt_Notes(MODULE * mod)2525 static void pt_Notes(MODULE *mod)
2526 {
2527 	SWORD channel;
2528 	MP_CONTROL *a;
2529 	UBYTE c,inst;
2530 	int tr,funky; /* funky is set to indicate note or instrument change */
2531 
2532 	for (channel=0;channel<mod->numchn;channel++) {
2533 		a=&mod->control[channel];
2534 
2535 		if (mod->sngpos>=mod->numpos) {
2536 			tr=mod->numtrk;
2537 			mod->numrow=0;
2538 		} else {
2539 			tr=mod->patterns[(mod->positions[mod->sngpos]*mod->numchn)+channel];
2540 			mod->numrow=mod->pattrows[mod->positions[mod->sngpos]];
2541 		}
2542 
2543 		a->row=(tr<mod->numtrk)?UniFindRow(mod->tracks[tr],mod->patpos):NULL;
2544 		a->newsamp=0;
2545 		if (!mod->vbtick) a->main.notedelay=0;
2546 
2547 		if (!a->row) continue;
2548 		UniSetRow(a->row);
2549 		funky=0;
2550 
2551 		while((c=UniGetByte()) != 0)
2552 			switch (c) {
2553 			case UNI_NOTE:
2554 				funky|=1;
2555 				a->oldnote=a->anote,a->anote=UniGetByte();
2556 				a->main.kick =KICK_NOTE;
2557 				a->main.start=-1;
2558 				a->sliding=0;
2559 
2560 				/* retrig tremolo and vibrato waves ? */
2561 				if (!(a->wavecontrol & 0x80)) a->trmpos=0;
2562 				if (!(a->wavecontrol & 0x08)) a->vibpos=0;
2563 				if (!a->panbwave) a->panbpos=0;
2564 				break;
2565 			case UNI_INSTRUMENT:
2566 				inst=UniGetByte();
2567 				if (inst>=mod->numins) break; /* safety valve */
2568 				funky|=2;
2569 				a->main.i=(mod->flags & UF_INST)?&mod->instruments[inst]:NULL;
2570 				a->retrig=0;
2571 				a->s3mtremor=0;
2572 				a->ultoffset=0;
2573 				a->main.sample=inst;
2574 				break;
2575 			default:
2576 				UniSkipOpcode();
2577 				break;
2578 			}
2579 
2580 		if (funky) {
2581 			INSTRUMENT *i;
2582 			SAMPLE *s;
2583 
2584 			if ((i=a->main.i) != NULL) {
2585 				if (i->samplenumber[a->anote] >= mod->numsmp) continue;
2586 				s=&mod->samples[i->samplenumber[a->anote]];
2587 				a->main.note=i->samplenote[a->anote];
2588 			} else {
2589 				a->main.note=a->anote;
2590 				s=&mod->samples[a->main.sample];
2591 			}
2592 
2593 			if (a->main.s!=s) {
2594 				a->main.s=s;
2595 				a->newsamp=a->main.period;
2596 			}
2597 
2598 			/* channel or instrument determined panning ? */
2599 			a->main.panning=mod->panning[channel];
2600 			if (s->flags & SF_OWNPAN)
2601 				a->main.panning=s->panning;
2602 			else if ((i)&&(i->flags & IF_OWNPAN))
2603 				a->main.panning=i->panning;
2604 
2605 			a->main.handle=s->handle;
2606 			a->speed=s->speed;
2607 
2608 			if (i) {
2609 				if ((mod->panflag)&&(i->flags & IF_PITCHPAN)
2610 				   &&(a->main.panning!=PAN_SURROUND)){
2611 					a->main.panning+=
2612 					    ((a->anote-i->pitpancenter)*i->pitpansep)/8;
2613 					if (a->main.panning<PAN_LEFT)
2614 						a->main.panning=PAN_LEFT;
2615 					else if (a->main.panning>PAN_RIGHT)
2616 						a->main.panning=PAN_RIGHT;
2617 				}
2618 				a->main.pitflg=i->pitflg;
2619 				a->main.volflg=i->volflg;
2620 				a->main.panflg=i->panflg;
2621 				a->main.nna=i->nnatype;
2622 				a->dca=i->dca;
2623 				a->dct=i->dct;
2624 			} else {
2625 				a->main.pitflg=a->main.volflg=a->main.panflg=0;
2626 				a->main.nna=a->dca=0;
2627 				a->dct=DCT_OFF;
2628 			}
2629 
2630 			if (funky&2) /* instrument change */ {
2631 				/* IT random volume variations: 0:8 bit fixed, and one bit for
2632 				   sign. */
2633 				a->volume=a->tmpvolume=s->volume;
2634 				if ((s)&&(i)) {
2635 					if (i->rvolvar) {
2636 						a->volume=a->tmpvolume=s->volume+
2637 						  ((s->volume*((SLONG)i->rvolvar*(SLONG)getrandom(512)
2638 						  ))/25600);
2639 						if (a->volume<0)
2640 							a->volume=a->tmpvolume=0;
2641 						else if (a->volume>64)
2642 							a->volume=a->tmpvolume=64;
2643 					}
2644 					if ((mod->panflag)&&(a->main.panning!=PAN_SURROUND)) {
2645 						a->main.panning+=((a->main.panning*((SLONG)i->rpanvar*
2646 						  (SLONG)getrandom(512)))/25600);
2647 						if (a->main.panning<PAN_LEFT)
2648 							a->main.panning=PAN_LEFT;
2649 						else if (a->main.panning>PAN_RIGHT)
2650 							a->main.panning=PAN_RIGHT;
2651 					}
2652 				}
2653 			}
2654 
2655 			a->wantedperiod=a->tmpperiod=
2656 			    GetPeriod(mod->flags, (UWORD)a->main.note<<1,a->speed);
2657 			a->main.keyoff=KEY_KICK;
2658 		}
2659 	}
2660 }
2661 
2662 /* Handles effects */
pt_EffectsPass1(MODULE * mod)2663 static void pt_EffectsPass1(MODULE *mod)
2664 {
2665 	SWORD channel;
2666 	MP_CONTROL *a;
2667 	MP_VOICE *aout;
2668 	int explicitslides;
2669 
2670 	for (channel=0;channel<mod->numchn;channel++) {
2671 		a=&mod->control[channel];
2672 
2673 		if ((aout=a->slave) != NULL) {
2674 			a->main.fadevol=aout->main.fadevol;
2675 			a->main.period=aout->main.period;
2676 			if (a->main.kick==KICK_KEYOFF)
2677 				a->main.keyoff=aout->main.keyoff;
2678 		}
2679 
2680 		if (!a->row) continue;
2681 		UniSetRow(a->row);
2682 
2683 		a->ownper=a->ownvol=0;
2684 		explicitslides = pt_playeffects(mod, channel, a);
2685 
2686 		/* continue volume slide if necessary for XM and IT */
2687 		if (mod->flags&UF_BGSLIDES) {
2688 			if (!explicitslides && a->sliding)
2689 				DoS3MVolSlide(mod->vbtick, mod->flags, a, 0);
2690 			else if (a->tmpvolume)
2691 				a->sliding = explicitslides;
2692 		}
2693 
2694 		if (!a->ownper)
2695 			a->main.period=a->tmpperiod;
2696 		if (!a->ownvol)
2697 			a->volume=a->tmpvolume;
2698 
2699 		if (a->main.s) {
2700 			if (a->main.i)
2701 				a->main.outvolume=
2702 				    (a->volume*a->main.s->globvol*a->main.i->globvol)>>10;
2703 			else
2704 				a->main.outvolume=(a->volume*a->main.s->globvol)>>4;
2705 			if (a->main.outvolume>256)
2706 				a->main.outvolume=256;
2707 			else if (a->main.outvolume<0)
2708 				a->main.outvolume=0;
2709 		}
2710 	}
2711 }
2712 
2713 /* NNA management */
pt_NNA(MODULE * mod)2714 static void pt_NNA(MODULE *mod)
2715 {
2716 	SWORD channel;
2717 	MP_CONTROL *a;
2718 
2719 	for (channel=0;channel<mod->numchn;channel++) {
2720 		a=&mod->control[channel];
2721 
2722 		if (a->main.kick==KICK_NOTE) {
2723 			BOOL kill=0;
2724 
2725 			if (a->slave) {
2726 				MP_VOICE *aout;
2727 
2728 				aout=a->slave;
2729 				if (aout->main.nna & NNA_MASK) {
2730 					/* Make sure the old MP_VOICE channel knows it has no
2731 					   master now ! */
2732 					a->slave=NULL;
2733 					/* assume the channel is taken by NNA */
2734 					aout->mflag=0;
2735 
2736 					switch (aout->main.nna) {
2737 					case NNA_CONTINUE: /* continue note, do nothing */
2738 						break;
2739 					case NNA_OFF: /* note off */
2740 						aout->main.keyoff|=KEY_OFF;
2741 						if ((!(aout->main.volflg & EF_ON))||
2742 							  (aout->main.volflg & EF_LOOP))
2743 							aout->main.keyoff=KEY_KILL;
2744 						break;
2745 					case NNA_FADE:
2746 						aout->main.keyoff |= KEY_FADE;
2747 						break;
2748 					}
2749 				}
2750 			}
2751 
2752 			if (a->dct!=DCT_OFF) {
2753 				int t;
2754 
2755 				for (t=0;t<NUMVOICES(mod);t++)
2756 					if ((!Voice_Stopped_internal(t))&&
2757 					   (mod->voice[t].masterchn==channel)&&
2758 					   (a->main.sample==mod->voice[t].main.sample)) {
2759 						kill=0;
2760 						switch (a->dct) {
2761 						case DCT_NOTE:
2762 							if (a->main.note==mod->voice[t].main.note)
2763 								kill=1;
2764 							break;
2765 						case DCT_SAMPLE:
2766 							if (a->main.handle==mod->voice[t].main.handle)
2767 								kill=1;
2768 							break;
2769 						case DCT_INST:
2770 							kill=1;
2771 							break;
2772 						}
2773 						if (kill)
2774 							switch (a->dca) {
2775 							case DCA_CUT:
2776 								mod->voice[t].main.fadevol=0;
2777 								break;
2778 							case DCA_OFF:
2779 								mod->voice[t].main.keyoff|=KEY_OFF;
2780 								if ((!(mod->voice[t].main.volflg&EF_ON))||
2781 								    (mod->voice[t].main.volflg&EF_LOOP))
2782 									mod->voice[t].main.keyoff=KEY_KILL;
2783 								break;
2784 							case DCA_FADE:
2785 								mod->voice[t].main.keyoff|=KEY_FADE;
2786 								break;
2787 							}
2788 					}
2789 			}
2790 		} /* if (a->main.kick==KICK_NOTE) */
2791 	}
2792 }
2793 
2794 /* Setup module and NNA voices */
pt_SetupVoices(MODULE * mod)2795 static void pt_SetupVoices(MODULE *mod)
2796 {
2797 	SWORD channel;
2798 	MP_CONTROL *a;
2799 	MP_VOICE *aout;
2800 
2801 	for (channel=0;channel<mod->numchn;channel++) {
2802 		a=&mod->control[channel];
2803 
2804 		if (a->main.notedelay) continue;
2805 		if (a->main.kick==KICK_NOTE) {
2806 			/* if no channel was cut above, find an empty or quiet channel
2807 			   here */
2808 			if (mod->flags&UF_NNA) {
2809 				if (!a->slave) {
2810 					int newchn;
2811 
2812 					if ((newchn=MP_FindEmptyChannel(mod))!=-1)
2813 						a->slave=&mod->voice[a->slavechn=newchn];
2814 				}
2815 			} else
2816 				a->slave=&mod->voice[a->slavechn=channel];
2817 
2818 			/* assign parts of MP_VOICE only done for a KICK_NOTE */
2819 			if ((aout=a->slave) != NULL) {
2820 				if (aout->mflag && aout->master) aout->master->slave=NULL;
2821 				aout->master=a;
2822 				a->slave=aout;
2823 				aout->masterchn=channel;
2824 				aout->mflag=1;
2825 			}
2826 		} else
2827 			aout=a->slave;
2828 
2829 		if (aout)
2830 			aout->main=a->main;
2831 		a->main.kick=KICK_ABSENT;
2832 	}
2833 }
2834 
2835 /* second effect pass */
pt_EffectsPass2(MODULE * mod)2836 static void pt_EffectsPass2(MODULE *mod)
2837 {
2838 	SWORD channel;
2839 	MP_CONTROL *a;
2840 	UBYTE c;
2841 
2842 	for (channel=0;channel<mod->numchn;channel++) {
2843 		a=&mod->control[channel];
2844 
2845 		if (!a->row) continue;
2846 		UniSetRow(a->row);
2847 
2848 		while((c=UniGetByte()) != 0)
2849 			if (c==UNI_ITEFFECTS0) {
2850 				c=UniGetByte();
2851 				if ((c>>4)==SS_S7EFFECTS)
2852 					DoNNAEffects(mod, a, c&0xf);
2853 			} else
2854 				UniSkipOpcode();
2855 	}
2856 }
2857 
Player_HandleTick(void)2858 void Player_HandleTick(void)
2859 {
2860 	SWORD channel;
2861 	int max_volume;
2862 
2863 #if 0
2864 	/* don't handle the very first ticks, this allows the other hardware to
2865 	   settle down so we don't loose any starting notes */
2866 	if (isfirst) {
2867 		isfirst--;
2868 		return;
2869 	}
2870 #endif
2871 
2872 	if ((!pf)||(pf->forbid)||(pf->sngpos>=pf->numpos)) return;
2873 
2874 	/* update time counter (sngtime is in milliseconds (in fact 2^-10)) */
2875 	pf->sngremainder+=(1<<9)*5; /* thus 2.5*(1<<10), since fps=0.4xtempo */
2876 	pf->sngtime+=pf->sngremainder/pf->bpm;
2877 	pf->sngremainder%=pf->bpm;
2878 
2879 	if (++pf->vbtick>=pf->sngspd) {
2880 		if (pf->pat_repcrazy)
2881 			pf->pat_repcrazy=0; /* play 2 times row 0 */
2882 		else
2883 			pf->patpos++;
2884 		pf->vbtick=0;
2885 
2886 		/* process pattern-delay. pf->patdly2 is the counter and pf->patdly is
2887 		   the command memory. */
2888 		if (pf->patdly)
2889 			pf->patdly2=pf->patdly,pf->patdly=0;
2890 		if (pf->patdly2) {
2891 			/* patterndelay active */
2892 			if (--pf->patdly2)
2893 				/* so turn back pf->patpos by 1 */
2894 				if (pf->patpos) pf->patpos--;
2895 		}
2896 
2897 		/* do we have to get a new patternpointer ? (when pf->patpos reaches the
2898 		   pattern size, or when a patternbreak is active) */
2899 		if (((pf->patpos>=pf->numrow)&&(pf->numrow>0))&&(!pf->posjmp))
2900 			pf->posjmp=3;
2901 
2902 		if (pf->posjmp) {
2903 			pf->patpos=pf->numrow?(pf->patbrk%pf->numrow):0;
2904 			pf->pat_repcrazy=0;
2905 			pf->sngpos+=(pf->posjmp-2);
2906 			for (channel=0;channel<pf->numchn;channel++)
2907 				pf->control[channel].pat_reppos=-1;
2908 
2909 			pf->patbrk=pf->posjmp=0;
2910 
2911 			if (pf->sngpos<0) pf->sngpos=(SWORD)(pf->numpos-1);
2912 
2913 			/* handle the "---" (end of song) pattern since it can occur
2914 			   *inside* the module in some formats */
2915 			if ((pf->sngpos>=pf->numpos)||
2916 				(pf->positions[pf->sngpos]==LAST_PATTERN)) {
2917 				if (!pf->wrap) return;
2918 				if (!(pf->sngpos=pf->reppos)) {
2919 				    pf->volume=pf->initvolume>128?128:pf->initvolume;
2920 					if(pf->initspeed!=0)
2921 						pf->sngspd=pf->initspeed<32?pf->initspeed:32;
2922 					else
2923 						pf->sngspd=6;
2924 					pf->bpm=pf->inittempo<32?32:pf->inittempo;
2925 				}
2926 			}
2927 		}
2928 
2929 		if (!pf->patdly2)
2930 			pt_Notes(pf);
2931 	}
2932 
2933 	/* Fade global volume if enabled and we're playing the last pattern */
2934 	if (((pf->sngpos==pf->numpos-1)||
2935 		 (pf->positions[pf->sngpos+1]==LAST_PATTERN))&&
2936 	    (pf->fadeout))
2937 		max_volume=pf->numrow?((pf->numrow-pf->patpos)*128)/pf->numrow:0;
2938 	else
2939 		max_volume=128;
2940 
2941 	pt_EffectsPass1(pf);
2942 	if (pf->flags&UF_NNA)
2943 		pt_NNA(pf);
2944 	pt_SetupVoices(pf);
2945 	pt_EffectsPass2(pf);
2946 
2947 	/* now set up the actual hardware channel playback information */
2948 	pt_UpdateVoices(pf, max_volume);
2949 }
2950 
Player_Init_internal(MODULE * mod)2951 static void Player_Init_internal(MODULE* mod)
2952 {
2953 	int t;
2954 
2955 	for (t=0;t<mod->numchn;t++) {
2956 		mod->control[t].main.chanvol=mod->chanvol[t];
2957 		mod->control[t].main.panning=mod->panning[t];
2958 	}
2959 
2960 	mod->sngtime=0;
2961 	mod->sngremainder=0;
2962 
2963 	mod->pat_repcrazy=0;
2964 	mod->sngpos=0;
2965 	if(mod->initspeed!=0)
2966 		mod->sngspd=mod->initspeed<32?mod->initspeed:32;
2967 	else
2968 		mod->sngspd=6;
2969 	mod->volume=mod->initvolume>128?128:mod->initvolume;
2970 
2971 	mod->vbtick=mod->sngspd;
2972 	mod->patdly=0;
2973 	mod->patdly2=0;
2974 	mod->bpm=mod->inittempo<32?32:mod->inittempo;
2975 	mod->realchn=0;
2976 
2977 	mod->patpos=0;
2978 	mod->posjmp=2; /* make sure the player fetches the first note */
2979 	mod->numrow=-1;
2980 	mod->patbrk=0;
2981 }
2982 
Player_Init(MODULE * mod)2983 int Player_Init(MODULE* mod)
2984 {
2985 	mod->extspd=1;
2986 	mod->panflag=1;
2987 	mod->wrap=0;
2988 	mod->loop=1;
2989 	mod->fadeout=0;
2990 
2991 	mod->relspd=0;
2992 
2993 	/* make sure the player doesn't start with garbage */
2994 	if (!(mod->control=(MP_CONTROL*)MikMod_calloc(mod->numchn,sizeof(MP_CONTROL))))
2995 		return 1;
2996 	if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE))))
2997 		return 1;
2998 
2999 	/* mod->numvoices was used during loading to clamp md_sngchn.
3000 	   After loading it's used to remember how big mod->voice is.
3001 	*/
3002 	mod->numvoices = md_sngchn;
3003 
3004 	Player_Init_internal(mod);
3005 	return 0;
3006 }
3007 
Player_Exit_internal(MODULE * mod)3008 void Player_Exit_internal(MODULE* mod)
3009 {
3010 	if (!mod)
3011 		return;
3012 
3013 	/* Stop playback if necessary */
3014 	if (mod==pf) {
3015 		Player_Stop_internal();
3016 		pf=NULL;
3017 	}
3018 
3019 	MikMod_free(mod->control);
3020 	MikMod_free(mod->voice);
3021 	mod->control=NULL;
3022 	mod->voice=NULL;
3023 }
3024 
Player_Exit(MODULE * mod)3025 void Player_Exit(MODULE* mod)
3026 {
3027 	MUTEX_LOCK(vars);
3028 	Player_Exit_internal(mod);
3029 	MUTEX_UNLOCK(vars);
3030 }
3031 
Player_SetVolume(SWORD volume)3032 MIKMODAPI void Player_SetVolume(SWORD volume)
3033 {
3034 	MUTEX_LOCK(vars);
3035 	if (pf) {
3036 		pf->volume=(volume<0)?0:(volume>128)?128:volume;
3037 		pf->initvolume=pf->volume;
3038 	}
3039 	MUTEX_UNLOCK(vars);
3040 }
3041 
Player_GetModule(void)3042 MIKMODAPI MODULE* Player_GetModule(void)
3043 {
3044 	MODULE* result;
3045 
3046 	MUTEX_LOCK(vars);
3047 	result=pf;
3048 	MUTEX_UNLOCK(vars);
3049 
3050 	return result;
3051 }
3052 
Player_Start(MODULE * mod)3053 MIKMODAPI void Player_Start(MODULE *mod)
3054 {
3055 	int t;
3056 
3057 	if (!mod)
3058 		return;
3059 
3060 	if (!MikMod_Active())
3061 		MikMod_EnableOutput();
3062 
3063 	mod->forbid=0;
3064 
3065 	MUTEX_LOCK(vars);
3066 	if (pf!=mod) {
3067 		/* new song is being started, so completely stop out the old one. */
3068 		if (pf) pf->forbid=1;
3069 		for (t=0;t<md_sngchn;t++) Voice_Stop_internal(t);
3070 	}
3071 	pf=mod;
3072 	MUTEX_UNLOCK(vars);
3073 }
3074 
Player_Stop_internal(void)3075 void Player_Stop_internal(void)
3076 {
3077 	if (!md_sfxchn) MikMod_DisableOutput_internal();
3078 	if (pf) pf->forbid=1;
3079 	pf=NULL;
3080 }
3081 
Player_Stop(void)3082 MIKMODAPI void Player_Stop(void)
3083 {
3084 	MUTEX_LOCK(vars);
3085 		Player_Stop_internal();
3086 	MUTEX_UNLOCK(vars);
3087 }
3088 
Player_Active(void)3089 MIKMODAPI BOOL Player_Active(void)
3090 {
3091 	BOOL result=0;
3092 
3093 	MUTEX_LOCK(vars);
3094 	if (pf)
3095 		result=(!(pf->sngpos>=pf->numpos));
3096 	MUTEX_UNLOCK(vars);
3097 
3098 	return result;
3099 }
3100 
Player_NextPosition(void)3101 MIKMODAPI void Player_NextPosition(void)
3102 {
3103 	MUTEX_LOCK(vars);
3104 	if (pf) {
3105 		int t;
3106 
3107 		pf->forbid=1;
3108 		pf->posjmp=3;
3109 		pf->patbrk=0;
3110 		pf->vbtick=pf->sngspd;
3111 
3112 		for (t=0;t<NUMVOICES(pf);t++) {
3113 			Voice_Stop_internal(t);
3114 			pf->voice[t].main.i=NULL;
3115 			pf->voice[t].main.s=NULL;
3116 		}
3117 		for (t=0;t<pf->numchn;t++) {
3118 			pf->control[t].main.i=NULL;
3119 			pf->control[t].main.s=NULL;
3120 		}
3121 		pf->forbid=0;
3122 	}
3123 	MUTEX_UNLOCK(vars);
3124 }
3125 
Player_PrevPosition(void)3126 MIKMODAPI void Player_PrevPosition(void)
3127 {
3128 	MUTEX_LOCK(vars);
3129 	if (pf) {
3130 		int t;
3131 
3132 		pf->forbid=1;
3133 		pf->posjmp=1;
3134 		pf->patbrk=0;
3135 		pf->vbtick=pf->sngspd;
3136 
3137 		for (t=0;t<NUMVOICES(pf);t++) {
3138 			Voice_Stop_internal(t);
3139 			pf->voice[t].main.i=NULL;
3140 			pf->voice[t].main.s=NULL;
3141 		}
3142 		for (t=0;t<pf->numchn;t++) {
3143 			pf->control[t].main.i=NULL;
3144 			pf->control[t].main.s=NULL;
3145 		}
3146 		pf->forbid=0;
3147 	}
3148 	MUTEX_UNLOCK(vars);
3149 }
3150 
Player_SetPosition(UWORD pos)3151 MIKMODAPI void Player_SetPosition(UWORD pos)
3152 {
3153 	MUTEX_LOCK(vars);
3154 	if (pf) {
3155 		int t;
3156 
3157 		pf->forbid=1;
3158 		if (pos>=pf->numpos) pos=pf->numpos;
3159 		pf->posjmp=2;
3160 		pf->patbrk=0;
3161 		pf->sngpos=pos;
3162 		pf->vbtick=pf->sngspd;
3163 
3164 		for (t=0;t<NUMVOICES(pf);t++) {
3165 			Voice_Stop_internal(t);
3166 			pf->voice[t].main.i=NULL;
3167 			pf->voice[t].main.s=NULL;
3168 		}
3169 		for (t=0;t<pf->numchn;t++) {
3170 			pf->control[t].main.i=NULL;
3171 			pf->control[t].main.s=NULL;
3172 		}
3173 		pf->forbid=0;
3174 
3175 		if (!pos)
3176 			Player_Init_internal(pf);
3177 	}
3178 	MUTEX_UNLOCK(vars);
3179 }
3180 
Player_Unmute_internal(SLONG arg1,va_list ap)3181 static void Player_Unmute_internal(SLONG arg1,va_list ap)
3182 {
3183 	SLONG t,arg2,arg3=0;
3184 
3185 	if (pf) {
3186 		switch (arg1) {
3187 		case MUTE_INCLUSIVE:
3188 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3189 			   (arg2>arg3)||(arg3>=pf->numchn))
3190 				return;
3191 			for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3192 				pf->control[arg2].muted=0;
3193 			break;
3194 		case MUTE_EXCLUSIVE:
3195 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3196 			   (arg2>arg3)||(arg3>=pf->numchn))
3197 				return;
3198 			for (t=0;t<pf->numchn;t++) {
3199 				if ((t>=arg2) && (t<=arg3))
3200 					continue;
3201 				pf->control[t].muted=0;
3202 			}
3203 			break;
3204 		default:
3205 			if (arg1<pf->numchn) pf->control[arg1].muted=0;
3206 			break;
3207 		}
3208 	}
3209 }
3210 
Player_Unmute(SLONG arg1,...)3211 MIKMODAPI void Player_Unmute(SLONG arg1, ...)
3212 {
3213 	va_list args;
3214 
3215 	va_start(args,arg1);
3216 	MUTEX_LOCK(vars);
3217 	Player_Unmute_internal(arg1,args);
3218 	MUTEX_UNLOCK(vars);
3219 	va_end(args);
3220 }
3221 
Player_Mute_internal(SLONG arg1,va_list ap)3222 static void Player_Mute_internal(SLONG arg1,va_list ap)
3223 {
3224 	SLONG t,arg2,arg3=0;
3225 
3226 	if (pf) {
3227 		switch (arg1) {
3228 		case MUTE_INCLUSIVE:
3229 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3230 			    (arg2>arg3)||(arg3>=pf->numchn))
3231 				return;
3232 			for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3233 				pf->control[arg2].muted=1;
3234 			break;
3235 		case MUTE_EXCLUSIVE:
3236 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3237 			    (arg2>arg3)||(arg3>=pf->numchn))
3238 				return;
3239 			for (t=0;t<pf->numchn;t++) {
3240 				if ((t>=arg2) && (t<=arg3))
3241 					continue;
3242 				pf->control[t].muted=1;
3243 			}
3244 			break;
3245 		default:
3246 			if (arg1<pf->numchn)
3247 				pf->control[arg1].muted=1;
3248 			break;
3249 		}
3250 	}
3251 }
3252 
Player_Mute(SLONG arg1,...)3253 MIKMODAPI void Player_Mute(SLONG arg1,...)
3254 {
3255 	va_list args;
3256 
3257 	va_start(args,arg1);
3258 	MUTEX_LOCK(vars);
3259 	Player_Mute_internal(arg1,args);
3260 	MUTEX_UNLOCK(vars);
3261 	va_end(args);
3262 }
3263 
Player_ToggleMute_internal(SLONG arg1,va_list ap)3264 static void Player_ToggleMute_internal(SLONG arg1,va_list ap)
3265 {
3266 	SLONG arg2,arg3=0;
3267 	ULONG t;
3268 
3269 	if (pf) {
3270 		switch (arg1) {
3271 		case MUTE_INCLUSIVE:
3272 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3273 			    (arg2>arg3)||(arg3>=pf->numchn))
3274 				return;
3275 			for (;arg2<pf->numchn && arg2<=arg3;arg2++)
3276 				pf->control[arg2].muted=1-pf->control[arg2].muted;
3277 			break;
3278 		case MUTE_EXCLUSIVE:
3279 			if (((!(arg2=va_arg(ap,SLONG)))&&(!(arg3=va_arg(ap,SLONG))))||
3280 			    (arg2>arg3)||(arg3>=pf->numchn))
3281 				return;
3282 			for (t=0;t<pf->numchn;t++) {
3283 				if ((t>=arg2) && (t<=arg3))
3284 					continue;
3285 				pf->control[t].muted=1-pf->control[t].muted;
3286 			}
3287 			break;
3288 		default:
3289 			if (arg1<pf->numchn)
3290 				pf->control[arg1].muted=1-pf->control[arg1].muted;
3291 			break;
3292 		}
3293 	}
3294 }
3295 
Player_ToggleMute(SLONG arg1,...)3296 MIKMODAPI void Player_ToggleMute(SLONG arg1,...)
3297 {
3298 	va_list args;
3299 
3300 	va_start(args,arg1);
3301 	MUTEX_LOCK(vars);
3302 	Player_ToggleMute_internal(arg1,args);
3303 	MUTEX_UNLOCK(vars);
3304 	va_end(args);
3305 }
3306 
Player_Muted(UBYTE chan)3307 MIKMODAPI BOOL Player_Muted(UBYTE chan)
3308 {
3309 	BOOL result=1;
3310 
3311 	MUTEX_LOCK(vars);
3312 	if (pf)
3313 		result=(chan<pf->numchn)?pf->control[chan].muted:1;
3314 	MUTEX_UNLOCK(vars);
3315 
3316 	return result;
3317 }
3318 
Player_GetChannelVoice(UBYTE chan)3319 MIKMODAPI int Player_GetChannelVoice(UBYTE chan)
3320 {
3321 	int result=0;
3322 
3323 	MUTEX_LOCK(vars);
3324 	if (pf)
3325 		result=(chan<pf->numchn)?pf->control[chan].slavechn:-1;
3326 	MUTEX_UNLOCK(vars);
3327 
3328 	return result;
3329 }
3330 
Player_GetChannelPeriod(UBYTE chan)3331 MIKMODAPI UWORD Player_GetChannelPeriod(UBYTE chan)
3332 {
3333 	UWORD result=0;
3334 
3335 	MUTEX_LOCK(vars);
3336 	if (pf)
3337 	    result=(chan<pf->numchn)?pf->control[chan].main.period:0;
3338 	MUTEX_UNLOCK(vars);
3339 
3340 	return result;
3341 }
3342 
Player_Paused_internal(void)3343 BOOL Player_Paused_internal(void)
3344 {
3345 	return pf?pf->forbid:1;
3346 }
3347 
Player_Paused(void)3348 MIKMODAPI BOOL Player_Paused(void)
3349 {
3350 	BOOL result;
3351 
3352 	MUTEX_LOCK(vars);
3353 	result=Player_Paused_internal();
3354 	MUTEX_UNLOCK(vars);
3355 
3356 	return result;
3357 }
3358 
Player_TogglePause(void)3359 MIKMODAPI void Player_TogglePause(void)
3360 {
3361 	MUTEX_LOCK(vars);
3362 	if (pf)
3363 		pf->forbid=1-pf->forbid;
3364 	MUTEX_UNLOCK(vars);
3365 }
3366 
Player_SetSpeed(UWORD speed)3367 MIKMODAPI void Player_SetSpeed(UWORD speed)
3368 {
3369 	MUTEX_LOCK(vars);
3370 	if (pf)
3371 		pf->sngspd=speed?(speed<32?speed:32):1;
3372 	MUTEX_UNLOCK(vars);
3373 }
3374 
Player_SetTempo(UWORD tempo)3375 MIKMODAPI void Player_SetTempo(UWORD tempo)
3376 {
3377 	if (tempo<32) tempo=32;
3378 	MUTEX_LOCK(vars);
3379 	if (pf) {
3380 		if ((!(pf->flags&UF_HIGHBPM))&&(tempo>255)) tempo=255;
3381 		pf->bpm=tempo;
3382 	}
3383 	MUTEX_UNLOCK(vars);
3384 }
3385 
Player_QueryVoices(UWORD numvoices,VOICEINFO * vinfo)3386 MIKMODAPI int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo)
3387 {
3388 	int i;
3389 
3390 	if (numvoices > md_sngchn)
3391 		numvoices = md_sngchn;
3392 
3393 	MUTEX_LOCK(vars);
3394 	if (pf)
3395 		for (i = 0; i < md_sngchn; i++) {
3396 			vinfo [i].i = pf->voice[i].main.i;
3397 			vinfo [i].s = pf->voice[i].main.s;
3398 			vinfo [i].panning = pf->voice [i].main.panning;
3399 			vinfo [i].volume = pf->voice [i].main.chanvol;
3400 			vinfo [i].period = pf->voice [i].main.period;
3401 			vinfo [i].kick = pf->voice [i].main.kick_flag;
3402 			pf->voice [i].main.kick_flag = 0;
3403 		}
3404 	MUTEX_UNLOCK(vars);
3405 
3406 	return numvoices;
3407 }
3408 
3409 /* Get current module order */
Player_GetOrder(void)3410 MIKMODAPI int Player_GetOrder(void)
3411 {
3412 	int ret;
3413 	MUTEX_LOCK(vars);
3414 	ret = pf ? pf->sngpos :0; /* pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0; */
3415 	MUTEX_UNLOCK(vars);
3416 	return ret;
3417 }
3418 
3419 /* Get current module row */
Player_GetRow(void)3420 MIKMODAPI int Player_GetRow(void)
3421 {
3422 	int ret;
3423 	MUTEX_LOCK(vars);
3424 	ret = pf ? pf->patpos : 0;
3425 	MUTEX_UNLOCK(vars);
3426 	return ret;
3427 }
3428 
3429 /* ex:set ts=4: */
3430