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