1 /*
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5
6 Most of this file is taken from the MikMod sound library, which is
7 (c) 1998, 1999 Miodrag Vallat and others - see file libunimod/AUTHORS
8 for complete list.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25 /* Interface to libunimod + module player */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif /* HAVE_CONFIG_H */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <math.h>
34
35 #ifdef SUNOS
36 extern long int random (void);
37 #endif
38
39 #ifndef NO_STRING_H
40 #include <string.h>
41 #else
42 #include <strings.h>
43 #endif
44
45 #include "timidity.h"
46 #include "common.h"
47 #include "instrum.h"
48 #include "playmidi.h"
49 #include "readmidi.h"
50 #include "tables.h"
51 #include "mod.h"
52 #include "output.h"
53 #include "controls.h"
54 #include "unimod.h"
55 #include "unimod_priv.h"
56 #include "mod2midi.h"
57
58 static BOOL mod_do_play (MODULE *);
59
60 int
load_module_file(struct timidity_file * tf,int mod_type)61 load_module_file (struct timidity_file *tf, int mod_type)
62 {
63 MODULE *mf;
64
65 #ifdef LOOKUP_HACK
66 ML_8bitsamples = 1;
67 #else
68 ML_8bitsamples = 0;
69 #endif
70 ML_monosamples = 1;
71
72 ML_RegisterAllLoaders ();
73 mf = ML_Load (tf->url, MOD_NUM_VOICES, 0);
74 if (ML_errno)
75 return 1;
76
77 current_file_info->file_type = mod_type;
78 load_module_samples (mf->samples, mf->numsmp, mod_type == IS_MOD_FILE);
79 mod_do_play (mf);
80 ML_Free (mf);
81 return 0;
82 }
83
84
85 int
get_module_type(char * fn)86 get_module_type (char *fn)
87 {
88 if (check_file_extension (fn, ".mod", 1)) /* Most common first */
89 return IS_MOD_FILE;
90
91 if (check_file_extension (fn, ".xm", 1)
92 || check_file_extension (fn, ".s3m", 1)
93 || check_file_extension (fn, ".it", 1)
94 || check_file_extension (fn, ".669", 1) /* Then the others in alphabetic order */
95 || check_file_extension (fn, ".amf", 1)
96 || check_file_extension (fn, ".dsm", 1)
97 || check_file_extension (fn, ".far", 1)
98 || check_file_extension (fn, ".gdm", 1)
99 || check_file_extension (fn, ".imf", 1)
100 || check_file_extension (fn, ".med", 1)
101 || check_file_extension (fn, ".mtm", 1)
102 || check_file_extension (fn, ".stm", 1)
103 || check_file_extension (fn, ".stx", 1)
104 || check_file_extension (fn, ".ult", 1)
105 || check_file_extension (fn, ".uni", 1))
106
107 return IS_S3M_FILE;
108
109 return IS_OTHER_FILE;
110 }
111
112 char *
get_module_title(struct timidity_file * tf,int mod_type)113 get_module_title (struct timidity_file *tf, int mod_type)
114 {
115 return ML_LoadTitle (tf->url);
116 }
117
118 /*========== Playing */
119
120 #define POS_NONE (-2) /* no loop position defined */
121
122 typedef struct ENVPR
123 {
124 UBYTE flg; /* envelope flag */
125 UBYTE pts; /* number of envelope points */
126 UBYTE susbeg; /* envelope sustain index begin */
127 UBYTE susend; /* envelope sustain index end */
128 UBYTE beg; /* envelope loop begin */
129 UBYTE end; /* envelope loop end */
130 SWORD p; /* current envelope counter */
131 UWORD a; /* envelope index a */
132 UWORD b; /* envelope index b */
133 ENVPT *env; /* envelope points */
134 }
135 ENVPR;
136
137 typedef struct MP_CONTROL
138 {
139 INSTRUMENT *i;
140 SAMPLE *s;
141 UBYTE sample; /* which sample number */
142 UBYTE note; /* the audible note as heard, direct rep of period */
143 SWORD outvolume; /* output volume (vol + sampcol + instvol) */
144 SBYTE chanvol; /* channel's "global" volume */
145 UWORD fadevol; /* fading volume rate */
146 SWORD panning; /* panning position */
147 UBYTE kick; /* if true = sample has to be restarted */
148 UWORD period; /* period to play the sample at */
149 UBYTE nna; /* New note action type + master/slave flags */
150
151 UBYTE volflg; /* volume envelope settings */
152 UBYTE panflg; /* panning envelope settings */
153 UBYTE pitflg; /* pitch envelope settings */
154
155 UBYTE keyoff; /* if true = fade out and stuff */
156 SWORD *data; /* which sample-data to play */
157 UBYTE notedelay; /* (used for note delay) */
158 SLONG start; /* The starting byte index in the sample */
159
160 UWORD ultoffset; /* fine sample offset memory */
161
162 struct MP_VOICE *slave; /* Audio Slave of current effects control channel */
163 UBYTE slavechn; /* Audio Slave of current effects control channel */
164 UBYTE anote; /* the note that indexes the audible */
165 UBYTE oldnote;
166 SWORD ownper;
167 SWORD ownvol;
168 UBYTE dca; /* duplicate check action */
169 UBYTE dct; /* duplicate check type */
170 UBYTE *row; /* row currently playing on this channel */
171 SBYTE retrig; /* retrig value (0 means don't retrig) */
172 ULONG speed; /* what finetune to use */
173 SWORD volume; /* amiga volume (0 t/m 64) to play the sample at */
174
175 SWORD tmpvolume; /* tmp volume */
176 UWORD tmpperiod; /* tmp period */
177 UWORD wantedperiod; /* period to slide to (with effect 3 or 5) */
178
179 UBYTE arpmem; /* arpeggio command memory */
180 UBYTE pansspd; /* panslide speed */
181 UWORD slidespeed; /* */
182 UWORD portspeed; /* noteslide speed (toneportamento) */
183
184 UBYTE s3mtremor; /* s3m tremor (effect I) counter */
185 UBYTE s3mtronof; /* s3m tremor ontime/offtime */
186 UBYTE s3mvolslide; /* last used volslide */
187 SBYTE sliding;
188 UBYTE s3mrtgspeed; /* last used retrig speed */
189 UBYTE s3mrtgslide; /* last used retrig slide */
190
191 UBYTE glissando; /* glissando (0 means off) */
192 UBYTE wavecontrol;
193
194 SBYTE vibpos; /* current vibrato position */
195 UBYTE vibspd; /* "" speed */
196 UBYTE vibdepth; /* "" depth */
197
198 SBYTE trmpos; /* current tremolo position */
199 UBYTE trmspd; /* "" speed */
200 UBYTE trmdepth; /* "" depth */
201
202 UBYTE fslideupspd;
203 UBYTE fslidednspd;
204 UBYTE fportupspd; /* fx E1 (extra fine portamento up) data */
205 UBYTE fportdnspd; /* fx E2 (extra fine portamento dn) data */
206 UBYTE ffportupspd; /* fx X1 (extra fine portamento up) data */
207 UBYTE ffportdnspd; /* fx X2 (extra fine portamento dn) data */
208
209 ULONG hioffset; /* last used high order of sample offset */
210 UWORD soffset; /* last used low order of sample-offset (effect 9) */
211
212 UBYTE sseffect; /* last used Sxx effect */
213 UBYTE ssdata; /* last used Sxx data info */
214 UBYTE chanvolslide; /* last used channel volume slide */
215
216 UBYTE panbwave; /* current panbrello waveform */
217 UBYTE panbpos; /* current panbrello position */
218 SBYTE panbspd; /* "" speed */
219 UBYTE panbdepth; /* "" depth */
220
221 UWORD newsamp; /* set to 1 upon a sample / inst change */
222 UBYTE voleffect; /* Volume Column Effect Memory as used by IT */
223 UBYTE voldata; /* Volume Column Data Memory */
224
225 SWORD pat_reppos; /* patternloop position */
226 UWORD pat_repcnt; /* times to loop */
227 }
228 MP_CONTROL;
229
230 /* Used by NNA only player (audio control. MP_CONTROL is used for full effects
231 control). */
232 typedef struct MP_VOICE
233 {
234 INSTRUMENT *i;
235 SAMPLE *s;
236 UBYTE sample; /* which instrument number */
237
238 SWORD volume; /* output volume (vol + sampcol + instvol) */
239 SWORD panning; /* panning position */
240 SBYTE chanvol; /* channel's "global" volume */
241 UWORD fadevol; /* fading volume rate */
242 UWORD period; /* period to play the sample at */
243
244 UBYTE volflg; /* volume envelope settings */
245 UBYTE panflg; /* panning envelope settings */
246 UBYTE pitflg; /* pitch envelope settings */
247
248 UBYTE keyoff; /* if true = fade out and stuff */
249 UBYTE kick; /* if true = sample has to be restarted */
250 UBYTE note; /* the audible note (as heard, direct rep of period) */
251 UBYTE nna; /* New note action type + master/slave flags */
252 SWORD *data; /* which sample-data to play */
253 SLONG start; /* The start byte index in the sample */
254
255 /* Below here is info NOT in MP_CONTROL!! */
256 ENVPR venv;
257 ENVPR penv;
258 ENVPR cenv;
259
260 UWORD avibpos; /* autovibrato pos */
261 UWORD aswppos; /* autovibrato sweep pos */
262
263 ULONG totalvol; /* total volume of channel (before global mixings) */
264
265 BOOL mflag;
266 SWORD masterchn;
267 UWORD masterperiod;
268
269 MP_CONTROL *master; /* index of "master" effects channel */
270 }
271 MP_VOICE;
272
273 typedef struct MP_STATUS
274 {
275 SWORD channel; /* channel we're working on */
276 UWORD oldsngspd; /* old song speed */
277 UWORD sngspd; /* current song speed */
278 SWORD volume; /* song volume (0-128) (or user volume) */
279 UWORD bpm; /* current beats-per-minute speed */
280 UWORD newbpm; /* next beats-per-minute speed */
281
282 UBYTE realchn; /* real number of channels used */
283 UBYTE totalchn; /* total number of channels used (incl NNAs) */
284
285 UWORD patpos; /* current row number */
286 SWORD sngpos; /* current song position */
287
288 UWORD numrow; /* number of rows on current pattern */
289 UWORD vbtick; /* tick counter (counts from 0 to sngspd) */
290
291 struct MP_CONTROL *control; /* Effects Channel info (size pf->numchn) */
292 struct MP_VOICE voice[MOD_NUM_VOICES]; /* Audio Voice information */
293
294 UBYTE globalslide; /* global volume slide rate */
295 UBYTE pat_repcrazy; /* module has just looped to position -1 */
296 UWORD patbrk; /* position where to start a new pattern */
297 UBYTE patdly; /* patterndelay counter (command memory) */
298 UBYTE patdly2; /* patterndelay counter (real one) */
299 SWORD posjmp; /* flag to indicate a jump is needed... */
300 int explicitslides;
301 }
302 MP_STATUS;
303
304 MODULE *pf = NULL; /* modfile being played */
305 static MP_CONTROL *a; /* current AUDTMP we're working on */
306 static MP_STATUS mp; /* player status */
307
308 static UBYTE VibratoTable[32] =
309 {
310 0, 24, 49, 74, 97, 120, 141, 161, 180, 197, 212, 224, 235, 244, 250, 253,
311 255, 253, 250, 244, 235, 224, 212, 197, 180, 161, 141, 120, 97, 74, 49, 24
312 };
313
314 static UBYTE avibtab[128] =
315 {
316 0, 1, 3, 4, 6, 7, 9, 10, 12, 14, 15, 17, 18, 20, 21, 23,
317 24, 25, 27, 28, 30, 31, 32, 34, 35, 36, 38, 39, 40, 41, 42, 44,
318 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 54, 55, 56, 57, 57, 58,
319 59, 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 63, 63, 63, 63,
320 64, 63, 63, 63, 63, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60, 59,
321 59, 58, 57, 57, 56, 55, 54, 54, 53, 52, 51, 50, 49, 48, 47, 46,
322 45, 44, 42, 41, 40, 39, 38, 36, 35, 34, 32, 31, 30, 28, 27, 25,
323 24, 23, 21, 20, 18, 17, 15, 14, 12, 10, 9, 7, 6, 4, 3, 1
324 };
325
326 static SBYTE PanbrelloTable[256] =
327 {
328 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
329 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
330 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
331 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64,
332 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60,
333 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46,
334 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26,
335 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2,
336 0, -2, -3, -5, -6, -8, -9, -11, -12, -14, -16, -17, -19, -20, -22, -23,
337 -24, -26, -27, -29, -30, -32, -33, -34, -36, -37, -38, -39, -41, -42, -43, -44,
338 -45, -46, -47, -48, -49, -50, -51, -52, -53, -54, -55, -56, -56, -57, -58, -59,
339 -59, -60, -60, -61, -61, -62, -62, -62, -63, -63, -63, -64, -64, -64, -64, -64,
340 -64, -64, -64, -64, -64, -64, -63, -63, -63, -62, -62, -62, -61, -61, -60, -60,
341 -59, -59, -58, -57, -56, -56, -55, -54, -53, -52, -51, -50, -49, -48, -47, -46,
342 -45, -44, -43, -42, -41, -39, -38, -37, -36, -34, -33, -32, -30, -29, -27, -26,
343 -24, -23, -22, -20, -19, -17, -16, -14, -12, -11, -9, -8, -6, -5, -3, -2
344 };
345
346 /* returns a random value between 0 and ceil-1, ceil must be a power of two */
347 static int
getrandom(int ceil)348 getrandom (int ceil)
349 {
350 #ifdef HAVE_SRANDOM
351 return random () & (ceil - 1);
352 #else
353 return (rand () * ceil) / (RAND_MAX + 1.0);
354 #endif
355 }
356
357 /* New Note Action Scoring System :
358 --------------------------------
359 1) total-volume (fadevol, chanvol, volume) is the main scorer.
360 2) a looping sample is a bonus x2
361 3) a foreground channel is a bonus x4
362 4) an active envelope with keyoff is a handicap -x2 */
363 static int
MP_FindEmptyChannel(void)364 MP_FindEmptyChannel (void)
365 {
366 MP_VOICE *a;
367 ULONG t, k, tvol, pp;
368
369 a = mp.voice;
370 for (t = 0; t < MOD_NUM_VOICES; t++)
371 {
372 /* allow us to take over a nonexisting sample */
373 if (!a->s)
374 return t;
375
376 if (((mp.voice[t].kick == KICK_ABSENT) || (mp.voice[t].kick == KICK_ENV)) &&
377 Voice_Stopped (t))
378 return t;
379 }
380
381 tvol = 0xffffffUL;
382 t = 0;
383 for (k = 0; k < MOD_NUM_VOICES; k++, a++)
384 if ((a->kick == KICK_ABSENT) || (a->kick == KICK_ENV))
385 {
386 pp = a->totalvol << ((a->s->flags & SF_LOOP) ? 1 : 0);
387 if ((a->master) && (a == a->master->slave))
388 pp <<= 2;
389
390 if (pp < tvol)
391 {
392 tvol = pp;
393 t = k;
394 }
395 }
396
397 if (tvol > 8000 * 7)
398 return -1;
399
400 return t;
401 }
402
GetPeriod(UWORD note,ULONG speed)403 static UWORD GetPeriod (UWORD note, ULONG speed)
404 {
405 if (pf->flags & UF_XMPERIODS)
406 return (pf->flags & UF_LINEAR) ? getlinearperiod (note, speed) : getlogperiod (note, speed);
407
408 return getoldperiod (note, speed);
409 }
410
411
412 static SWORD
Interpolate(SWORD p,SWORD p1,SWORD p2,SWORD v1,SWORD v2)413 Interpolate (SWORD p, SWORD p1, SWORD p2, SWORD v1, SWORD v2)
414 {
415 if ((p1 == p2) || (p == p1))
416 return v1;
417 return v1 + ((SLONG) ((p - p1) * (v2 - v1)) / (p2 - p1));
418 }
419
420
421 static SWORD
InterpolateEnv(SWORD p,ENVPT * a,ENVPT * b)422 InterpolateEnv (SWORD p, ENVPT * a, ENVPT * b)
423 {
424 return (Interpolate (p, a->pos, b->pos, a->val, b->val));
425 }
426
427 static SWORD
DoPan(SWORD envpan,SWORD pan)428 DoPan (SWORD envpan, SWORD pan)
429 {
430 int newpan;
431
432 newpan = pan + (((envpan - PAN_CENTER) * (128 - abs (pan - PAN_CENTER))) / 128);
433
434 return (newpan < PAN_LEFT) ? PAN_LEFT : (newpan > PAN_RIGHT ? PAN_RIGHT : newpan);
435 }
436
437 static void
StartEnvelope(ENVPR * t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susend,UBYTE beg,UBYTE end,ENVPT * p,UBYTE keyoff)438 StartEnvelope (ENVPR * t, UBYTE flg, UBYTE pts, UBYTE susbeg, UBYTE susend, UBYTE beg, UBYTE end, ENVPT * p, UBYTE keyoff)
439 {
440 t->flg = flg;
441 t->pts = pts;
442 t->susbeg = susbeg;
443 t->susend = susend;
444 t->beg = beg;
445 t->end = end;
446 t->env = p;
447 t->p = 0;
448 t->a = 0;
449 t->b = ((t->flg & EF_SUSTAIN) && (!(keyoff & KEY_OFF))) ? 0 : 1;
450
451 /* Imago Orpheus sometimes stores an extra initial point in the envelope */
452 if ((t->pts >= 2) && (t->env[0].pos == t->env[1].pos))
453 {
454 t->a++;
455 t->b++;
456 }
457
458 if (t->b >= t->pts)
459 t->b = t->pts - 1;
460 }
461
462 /* This procedure processes all envelope types, include volume, pitch, and
463 panning. Envelopes are defined by a set of points, each with a magnitude
464 [relating either to volume, panning position, or pitch modifier] and a tick
465 position.
466
467 Envelopes work in the following manner:
468
469 (a) Each tick the envelope is moved a point further in its progression. For
470 an accurate progression, magnitudes between two envelope points are
471 interpolated.
472
473 (b) When progression reaches a defined point on the envelope, values are
474 shifted to interpolate between this point and the next, and checks for
475 loops or envelope end are done.
476
477 Misc:
478 Sustain loops are loops that are only active as long as the keyoff flag is
479 clear. When a volume envelope terminates, so does the current fadeout. */
480 static SWORD
ProcessEnvelope(ENVPR * t,SWORD v,UBYTE keyoff)481 ProcessEnvelope (ENVPR * t, SWORD v, UBYTE keyoff)
482 {
483 if (t->flg & EF_ON)
484 {
485 UBYTE a, b; /* actual points in the envelope */
486 UWORD p; /* the 'tick counter' - real point being played */
487
488 a = t->a;
489 b = t->b;
490 p = t->p;
491
492 /* if sustain loop on one point (XM type), don't move and don't
493 interpolate when the point is reached */
494 if ((t->flg & EF_SUSTAIN) && (t->susbeg == t->susend) &&
495 (!(keyoff & KEY_OFF)) && (p == t->env[t->susbeg].pos))
496 v = t->env[t->susbeg].val;
497 else
498 {
499 /* compute the current envelope value between points a and b */
500 if (a == b)
501 v = t->env[a].val;
502 else
503 v = InterpolateEnv (p, &t->env[a], &t->env[b]);
504
505 p++;
506 /* pointer reached point b? */
507 if (p >= t->env[b].pos)
508 {
509 a = b++; /* shift points a and b */
510
511 /* Check for loops, sustain loops, or end of envelope. */
512 if ((t->flg & EF_SUSTAIN) && (!(keyoff & KEY_OFF)) && (b > t->susend))
513 {
514 a = t->susbeg;
515 b = (t->susbeg == t->susend) ? a : a + 1;
516 p = t->env[a].pos;
517 }
518 else if ((t->flg & EF_LOOP) && (b > t->end))
519 {
520 a = t->beg;
521 b = (t->beg == t->end) ? a : a + 1;
522 p = t->env[a].pos;
523 }
524 else
525 {
526 if (b >= t->pts)
527 {
528 if ((t->flg & EF_VOLENV) && (mp.channel != -1))
529 {
530 mp.voice[mp.channel].keyoff |= KEY_FADE;
531 if (!v)
532 mp.voice[mp.channel].fadevol = 0;
533 }
534 b--;
535 p--;
536 }
537 }
538 }
539 t->a = a;
540 t->b = b;
541 t->p = p;
542 }
543 }
544 return v;
545 }
546
547 /*========== Protracker effects */
548
549 static void
DoEEffects(UBYTE dat)550 DoEEffects (UBYTE dat)
551 {
552 UBYTE nib = dat & 0xf;
553
554 switch (dat >> 4)
555 {
556 case 0x0: /* hardware filter toggle, not supported */
557 break;
558 case 0x1: /* fineslide up */
559 if (a->period)
560 if (!mp.vbtick)
561 a->tmpperiod -= (nib << 2);
562 break;
563 case 0x2: /* fineslide dn */
564 if (a->period)
565 if (!mp.vbtick)
566 a->tmpperiod += (nib << 2);
567 break;
568 case 0x3: /* glissando ctrl */
569 a->glissando = nib;
570 break;
571 case 0x4: /* set vibrato waveform */
572 a->wavecontrol &= 0xf0;
573 a->wavecontrol |= nib;
574 break;
575 case 0x5: /* set finetune */
576 if (a->period)
577 {
578 if (pf->flags & UF_XMPERIODS)
579 a->speed = nib + 128;
580 else
581 a->speed = finetune[nib];
582 a->tmpperiod = GetPeriod ((UWORD) a->note << 1, a->speed);
583 }
584 break;
585 case 0x6: /* set patternloop */
586 if (mp.vbtick)
587 break;
588 if (nib)
589 { /* set reppos or repcnt ? */
590 /* set repcnt, so check if repcnt already is set, which means we
591 are already looping */
592 if (a->pat_repcnt)
593 a->pat_repcnt--; /* already looping, decrease counter */
594 else
595 {
596 #if 0
597 /* this would make walker.xm, shipped with Xsoundtracker,
598 play correctly, but it's better to remain compatible
599 with FT2 */
600 if ((!(pf->flags & UF_NOWRAP)) || (a->pat_reppos != POS_NONE))
601 #endif
602 a->pat_repcnt = nib; /* not yet looping, so set repcnt */
603 }
604
605 if (a->pat_repcnt)
606 { /* jump to reppos if repcnt>0 */
607 if (a->pat_reppos == POS_NONE)
608 a->pat_reppos = mp.patpos - 1;
609 if (a->pat_reppos == -1)
610 {
611 mp.pat_repcrazy = 1;
612 mp.patpos = 0;
613 }
614 else
615 mp.patpos = a->pat_reppos;
616 }
617 else
618 a->pat_reppos = POS_NONE;
619 }
620 else
621 a->pat_reppos = mp.patpos - 1; /* set reppos - can be (-1) */
622 break;
623 case 0x7: /* set tremolo waveform */
624 a->wavecontrol &= 0x0f;
625 a->wavecontrol |= nib << 4;
626 break;
627 case 0x8: /* set panning */
628 if (nib <= 8)
629 nib <<= 4;
630 else
631 nib *= 17;
632 a->panning = pf->panning[mp.channel] = nib;
633 break;
634 case 0x9: /* retrig note */
635 /* only retrigger if data nibble > 0 */
636 if (nib)
637 {
638 if (!a->retrig)
639 {
640 /* when retrig counter reaches 0, reset counter and restart
641 the sample */
642 if (a->period)
643 a->kick = KICK_NOTE;
644 a->retrig = nib;
645 }
646 a->retrig--; /* countdown */
647 }
648 break;
649 case 0xa: /* fine volume slide up */
650 if (mp.vbtick)
651 break;
652 a->tmpvolume += nib;
653 if (a->tmpvolume > 64)
654 a->tmpvolume = 64;
655 break;
656 case 0xb: /* fine volume slide dn */
657 if (mp.vbtick)
658 break;
659 a->tmpvolume -= nib;
660 if (a->tmpvolume < 0)
661 a->tmpvolume = 0;
662 break;
663 case 0xc: /* cut note */
664 /* When mp.vbtick reaches the cut-note value, turn the volume to
665 zero ( Just like on the amiga) */
666 if (mp.vbtick >= nib)
667 a->tmpvolume = 0; /* just turn the volume down */
668 break;
669 case 0xd: /* note delay */
670 /* delay the start of the sample until mp.vbtick==nib */
671 if (!mp.vbtick)
672 a->notedelay = nib;
673 else if (a->notedelay)
674 a->notedelay--;
675 break;
676 case 0xe: /* pattern delay */
677 if (mp.vbtick)
678 break;
679 if (!mp.patdly2)
680 mp.patdly = nib + 1; /* only once, when vbtick=0 */
681 break;
682 case 0xf: /* invert loop, not supported */
683 break;
684 }
685 }
686
687 static void
DoVibrato(void)688 DoVibrato (void)
689 {
690 UBYTE q;
691 UWORD temp = 0;
692
693 q = (a->vibpos >> 2) & 0x1f;
694
695 switch (a->wavecontrol & 3)
696 {
697 case 0: /* sine */
698 temp = VibratoTable[q];
699 break;
700 case 1: /* ramp down */
701 q <<= 3;
702 if (a->vibpos < 0)
703 q = 255 - q;
704 temp = q;
705 break;
706 case 2: /* square wave */
707 temp = 255;
708 break;
709 case 3: /* random wave */
710 temp = getrandom (256);
711 break;
712 }
713
714 temp *= a->vibdepth;
715 temp >>= 7;
716 temp <<= 2;
717
718 if (a->vibpos >= 0)
719 a->period = a->tmpperiod + temp;
720 else
721 a->period = a->tmpperiod - temp;
722
723 if (mp.vbtick)
724 a->vibpos += a->vibspd;
725 }
726
727 static void
DoTremolo(void)728 DoTremolo (void)
729 {
730 UBYTE q;
731 UWORD temp = 0;
732
733 q = (a->trmpos >> 2) & 0x1f;
734
735 switch ((a->wavecontrol >> 4) & 3)
736 {
737 case 0: /* sine */
738 temp = VibratoTable[q];
739 break;
740 case 1: /* ramp down */
741 q <<= 3;
742 if (a->trmpos < 0)
743 q = 255 - q;
744 temp = q;
745 break;
746 case 2: /* square wave */
747 temp = 255;
748 break;
749 case 3: /* random wave */
750 temp = getrandom (256);
751 break;
752 }
753 temp *= a->trmdepth;
754 temp >>= 6;
755
756 if (a->trmpos >= 0)
757 {
758 a->volume = a->tmpvolume + temp;
759 if (a->volume > 64)
760 a->volume = 64;
761 }
762 else
763 {
764 a->volume = a->tmpvolume - temp;
765 if (a->volume < 0)
766 a->volume = 0;
767 }
768
769 if (mp.vbtick)
770 a->trmpos += a->trmspd;
771 }
772
773 static void
DoVolSlide(UBYTE dat)774 DoVolSlide (UBYTE dat)
775 {
776 if (!mp.vbtick)
777 return;
778
779 if (dat & 0xf)
780 {
781 a->tmpvolume -= (dat & 0x0f);
782 if (a->tmpvolume < 0)
783 a->tmpvolume = 0;
784 }
785 else
786 {
787 a->tmpvolume += (dat >> 4);
788 if (a->tmpvolume > 64)
789 a->tmpvolume = 64;
790 }
791 }
792
793 static void
DoToneSlide(void)794 DoToneSlide (void)
795 {
796 if (mp.vbtick)
797 {
798 int dist;
799
800 /* We have to slide a->period towards a->wantedperiod, so compute the
801 difference between those two values */
802 dist = a->period - a->wantedperiod;
803
804 /* if they are equal or if portamentospeed is too big ... */
805 if ((!dist) || a->portspeed > abs (dist))
806 /* ...make tmpperiod equal tperiod */
807 a->tmpperiod = a->period = a->wantedperiod;
808 else if (dist > 0)
809 {
810 a->tmpperiod -= a->portspeed;
811 a->period -= a->portspeed; /* dist>0, slide up */
812 }
813 else
814 {
815 a->tmpperiod += a->portspeed;
816 a->period += a->portspeed; /* dist<0, slide down */
817 }
818 }
819 else
820 a->tmpperiod = a->period;
821 }
822
823 static void
DoArpeggio(UBYTE dat)824 DoArpeggio (UBYTE dat)
825 {
826 UBYTE note = a->note;
827
828 if (dat)
829 {
830 switch (mp.vbtick % 3)
831 {
832 case 1:
833 note += (dat >> 4);
834 break;
835 case 2:
836 note += (dat & 0xf);
837 break;
838 }
839 a->period = GetPeriod ((UWORD) note << 1, a->speed);
840 a->ownper = 1;
841 }
842 }
843
844 /*========== Scream Tracker effects */
845
846 static void
DoS3MVolSlide(UBYTE inf)847 DoS3MVolSlide (UBYTE inf)
848 {
849 UBYTE lo, hi;
850
851 if (inf)
852 a->s3mvolslide = inf;
853 else
854 inf = a->s3mvolslide;
855
856 lo = inf & 0xf;
857 hi = inf >> 4;
858
859 if (!lo)
860 {
861 if ((mp.vbtick) || (pf->flags & UF_S3MSLIDES))
862 a->tmpvolume += hi;
863 }
864 else if (!hi)
865 {
866 if ((mp.vbtick) || (pf->flags & UF_S3MSLIDES))
867 a->tmpvolume -= lo;
868 }
869 else if (lo == 0xf)
870 {
871 if (!mp.vbtick)
872 a->tmpvolume += (hi ? hi : 0xf);
873 }
874 else if (hi == 0xf)
875 {
876 if (!mp.vbtick)
877 a->tmpvolume -= (lo ? lo : 0xf);
878 }
879 else
880 return;
881
882 if (a->tmpvolume < 0)
883 a->tmpvolume = 0;
884 else if (a->tmpvolume > 64)
885 a->tmpvolume = 64;
886 }
887
888 static void
DoS3MSlideDn(UBYTE inf)889 DoS3MSlideDn (UBYTE inf)
890 {
891 UBYTE hi, lo;
892
893 if (inf)
894 a->slidespeed = inf;
895 else
896 inf = a->slidespeed;
897
898 hi = inf >> 4;
899 lo = inf & 0xf;
900
901 if (hi == 0xf)
902 {
903 if (!mp.vbtick)
904 a->tmpperiod += (UWORD) lo << 2;
905 }
906 else if (hi == 0xe)
907 {
908 if (!mp.vbtick)
909 a->tmpperiod += lo;
910 }
911 else
912 {
913 if (mp.vbtick)
914 a->tmpperiod += (UWORD) inf << 2;
915 }
916 }
917
918 static void
DoS3MSlideUp(UBYTE inf)919 DoS3MSlideUp (UBYTE inf)
920 {
921 UBYTE hi, lo;
922
923 if (inf)
924 a->slidespeed = inf;
925 else
926 inf = a->slidespeed;
927
928 hi = inf >> 4;
929 lo = inf & 0xf;
930
931 if (hi == 0xf)
932 {
933 if (!mp.vbtick)
934 a->tmpperiod -= (UWORD) lo << 2;
935 }
936 else if (hi == 0xe)
937 {
938 if (!mp.vbtick)
939 a->tmpperiod -= lo;
940 }
941 else
942 {
943 if (mp.vbtick)
944 a->tmpperiod -= (UWORD) inf << 2;
945 }
946 }
947
948 static void
DoS3MTremor(UBYTE inf)949 DoS3MTremor (UBYTE inf)
950 {
951 UBYTE on, off;
952
953 if (inf)
954 a->s3mtronof = inf;
955 else
956 {
957 inf = a->s3mtronof;
958 if (!inf)
959 return;
960 }
961
962 if (!mp.vbtick)
963 return;
964
965 on = (inf >> 4) + 1;
966 off = (inf & 0xf) + 1;
967 a->s3mtremor %= (on + off);
968 a->volume = (a->s3mtremor < on) ? a->tmpvolume : 0;
969 a->s3mtremor++;
970 }
971
972 static void
DoS3MRetrig(UBYTE inf)973 DoS3MRetrig (UBYTE inf)
974 {
975 if (inf)
976 {
977 a->s3mrtgslide = inf >> 4;
978 a->s3mrtgspeed = inf & 0xf;
979 }
980
981 /* only retrigger if low nibble > 0 */
982 if (a->s3mrtgspeed > 0)
983 {
984 if (!a->retrig)
985 {
986 /* when retrig counter reaches 0, reset counter and restart the
987 sample */
988 if (a->kick != KICK_NOTE)
989 a->kick = KICK_KEYOFF;
990 a->retrig = a->s3mrtgspeed;
991
992 if ((mp.vbtick) || (pf->flags & UF_S3MSLIDES))
993 {
994 switch (a->s3mrtgslide)
995 {
996 case 1:
997 case 2:
998 case 3:
999 case 4:
1000 case 5:
1001 a->tmpvolume -= (1 << (a->s3mrtgslide - 1));
1002 break;
1003 case 6:
1004 a->tmpvolume = (2 * a->tmpvolume) / 3;
1005 break;
1006 case 7:
1007 a->tmpvolume >>= 1;
1008 break;
1009 case 9:
1010 case 0xa:
1011 case 0xb:
1012 case 0xc:
1013 case 0xd:
1014 a->tmpvolume += (1 << (a->s3mrtgslide - 9));
1015 break;
1016 case 0xe:
1017 a->tmpvolume = (3 * a->tmpvolume) >> 1;
1018 break;
1019 case 0xf:
1020 a->tmpvolume = a->tmpvolume << 1;
1021 break;
1022 }
1023 if (a->tmpvolume < 0)
1024 a->tmpvolume = 0;
1025 else if (a->tmpvolume > 64)
1026 a->tmpvolume = 64;
1027 }
1028 }
1029 a->retrig--; /* countdown */
1030 }
1031 }
1032
1033 static void
DoS3MSpeed(UBYTE speed)1034 DoS3MSpeed (UBYTE speed)
1035 {
1036 if (mp.vbtick || mp.patdly2)
1037 return;
1038
1039 if (speed > 128)
1040 speed -= 128;
1041 if (speed)
1042 {
1043 mp.sngspd = speed;
1044 mp.vbtick = 0;
1045 }
1046 }
1047
1048 static void
DoS3MTempo(UBYTE tempo)1049 DoS3MTempo (UBYTE tempo)
1050 {
1051 if (mp.vbtick || mp.patdly2)
1052 return;
1053
1054 mp.newbpm = (tempo < 32) ? 32 : tempo;
1055 }
1056
1057 static void
DoS3MFineVibrato(void)1058 DoS3MFineVibrato (void)
1059 {
1060 UBYTE q;
1061 UWORD temp = 0;
1062
1063 q = (a->vibpos >> 2) & 0x1f;
1064
1065 switch (a->wavecontrol & 3)
1066 {
1067 case 0: /* sine */
1068 temp = VibratoTable[q];
1069 break;
1070 case 1: /* ramp down */
1071 q <<= 3;
1072 if (a->vibpos < 0)
1073 q = 255 - q;
1074 temp = q;
1075 break;
1076 case 2: /* square wave */
1077 temp = 255;
1078 break;
1079 case 3: /* random */
1080 temp = getrandom (256);
1081 break;
1082 }
1083
1084 temp *= a->vibdepth;
1085 temp >>= 8;
1086
1087 if (a->vibpos >= 0)
1088 a->period = a->tmpperiod + temp;
1089 else
1090 a->period = a->tmpperiod - temp;
1091
1092 a->vibpos += a->vibspd;
1093 }
1094
1095 static void
DoS3MTremolo(void)1096 DoS3MTremolo (void)
1097 {
1098 UBYTE q;
1099 UWORD temp = 0;
1100
1101 q = (a->trmpos >> 2) & 0x1f;
1102
1103 switch ((a->wavecontrol >> 4) & 3)
1104 {
1105 case 0: /* sine */
1106 temp = VibratoTable[q];
1107 break;
1108 case 1: /* ramp down */
1109 q <<= 3;
1110 if (a->trmpos < 0)
1111 q = 255 - q;
1112 temp = q;
1113 break;
1114 case 2: /* square wave */
1115 temp = 255;
1116 break;
1117 case 3: /* random */
1118 temp = getrandom (256);
1119 break;
1120 }
1121
1122 temp *= a->trmdepth;
1123 temp >>= 7;
1124
1125 if (a->trmpos >= 0)
1126 {
1127 a->volume = a->tmpvolume + temp;
1128 if (a->volume > 64)
1129 a->volume = 64;
1130 }
1131 else
1132 {
1133 a->volume = a->tmpvolume - temp;
1134 if (a->volume < 0)
1135 a->volume = 0;
1136 }
1137
1138 if (mp.vbtick)
1139 a->trmpos += a->trmspd;
1140 }
1141
1142 /*========== Fast Tracker effects */
1143
1144 static void
DoXMVolSlide(UBYTE inf)1145 DoXMVolSlide (UBYTE inf)
1146 {
1147 UBYTE lo, hi;
1148
1149 mp.explicitslides = 2;
1150
1151 if (inf)
1152 a->s3mvolslide = inf;
1153 else
1154 inf = a->s3mvolslide;
1155
1156 if (!mp.vbtick)
1157 return;
1158
1159 lo = inf & 0xf;
1160 hi = inf >> 4;
1161
1162 if (!hi)
1163 {
1164 a->tmpvolume -= lo;
1165 if (a->tmpvolume < 0)
1166 a->tmpvolume = 0;
1167 }
1168 else
1169 {
1170 a->tmpvolume += hi;
1171 if (a->tmpvolume > 64)
1172 a->tmpvolume = 64;
1173 }
1174 }
1175
1176 static void
DoXMGlobalSlide(UBYTE inf)1177 DoXMGlobalSlide (UBYTE inf)
1178 {
1179 if (mp.vbtick)
1180 {
1181 if (inf)
1182 mp.globalslide = inf;
1183 else
1184 inf = mp.globalslide;
1185 if (inf & 0xf0)
1186 inf &= 0xf0;
1187 mp.volume = mp.volume + ((inf >> 4) - (inf & 0xf)) * 2;
1188
1189 if (mp.volume < 0)
1190 mp.volume = 0;
1191 else if (mp.volume > 128)
1192 mp.volume = 128;
1193 }
1194 }
1195
1196 static void
DoXMPanSlide(UBYTE inf)1197 DoXMPanSlide (UBYTE inf)
1198 {
1199 UBYTE lo, hi;
1200 SWORD pan;
1201
1202 if (inf)
1203 a->pansspd = inf;
1204 else
1205 inf = a->pansspd;
1206
1207 if (!mp.vbtick)
1208 return;
1209
1210 lo = inf & 0xf;
1211 hi = inf >> 4;
1212
1213 /* slide right has absolute priority */
1214 if (hi)
1215 lo = 0;
1216
1217 pan = ((a->panning == PAN_SURROUND) ? PAN_CENTER : a->panning) + hi - lo;
1218
1219 a->panning = (pan < PAN_LEFT) ? PAN_LEFT : (pan > PAN_RIGHT ? PAN_RIGHT : pan);
1220 }
1221
1222 static void
DoXMExtraFineSlideUp(UBYTE inf)1223 DoXMExtraFineSlideUp (UBYTE inf)
1224 {
1225 if (!mp.vbtick)
1226 {
1227 a->period -= inf;
1228 a->tmpperiod -= inf;
1229 }
1230 }
1231
1232 static void
DoXMExtraFineSlideDown(UBYTE inf)1233 DoXMExtraFineSlideDown (UBYTE inf)
1234 {
1235 if (!mp.vbtick)
1236 {
1237 a->period += inf;
1238 a->tmpperiod += inf;
1239 }
1240 }
1241
1242 /*========== Impulse Tracker effects */
1243
1244 static void
DoITChanVolSlide(UBYTE inf)1245 DoITChanVolSlide (UBYTE inf)
1246 {
1247 UBYTE lo, hi;
1248
1249 if (inf)
1250 a->chanvolslide = inf;
1251 inf = a->chanvolslide;
1252
1253 lo = inf & 0xf;
1254 hi = inf >> 4;
1255
1256 if (!hi)
1257 a->chanvol -= lo;
1258 else if (!lo)
1259 {
1260 a->chanvol += hi;
1261 }
1262 else if (hi == 0xf)
1263 {
1264 if (!mp.vbtick)
1265 a->chanvol -= lo;
1266 }
1267 else if (lo == 0xf)
1268 {
1269 if (!mp.vbtick)
1270 a->chanvol += hi;
1271 }
1272
1273 if (a->chanvol < 0)
1274 a->chanvol = 0;
1275 if (a->chanvol > 64)
1276 a->chanvol = 64;
1277 }
1278
1279 static void
DoITGlobalSlide(UBYTE inf)1280 DoITGlobalSlide (UBYTE inf)
1281 {
1282 UBYTE lo, hi;
1283
1284 if (inf)
1285 mp.globalslide = inf;
1286 inf = mp.globalslide;
1287
1288 lo = inf & 0xf;
1289 hi = inf >> 4;
1290
1291 if (!lo)
1292 {
1293 if (mp.vbtick)
1294 mp.volume += hi;
1295 }
1296 else if (!hi)
1297 {
1298 if (mp.vbtick)
1299 mp.volume -= lo;
1300 }
1301 else if (lo == 0xf)
1302 {
1303 if (!mp.vbtick)
1304 mp.volume += hi;
1305 }
1306 else if (hi == 0xf)
1307 {
1308 if (!mp.vbtick)
1309 mp.volume -= lo;
1310 }
1311
1312 if (mp.volume < 0)
1313 mp.volume = 0;
1314 if (mp.volume > 128)
1315 mp.volume = 128;
1316 }
1317
1318 static void
DoITPanSlide(UBYTE inf)1319 DoITPanSlide (UBYTE inf)
1320 {
1321 UBYTE lo, hi;
1322 SWORD pan;
1323
1324 if (inf)
1325 a->pansspd = inf;
1326 else
1327 inf = a->pansspd;
1328
1329 lo = inf & 0xf;
1330 hi = inf >> 4;
1331
1332 pan = (a->panning == PAN_SURROUND) ? PAN_CENTER : a->panning;
1333
1334 if (!hi)
1335 pan += lo << 2;
1336 else if (!lo)
1337 {
1338 pan -= hi << 2;
1339 }
1340 else if (hi == 0xf)
1341 {
1342 if (!mp.vbtick)
1343 pan += lo << 2;
1344 }
1345 else if (lo == 0xf)
1346 {
1347 if (!mp.vbtick)
1348 pan -= hi << 2;
1349 }
1350 a->panning = /*pf->panning[mp.channel]= */
1351 (pan < PAN_LEFT) ? PAN_LEFT : (pan > PAN_RIGHT ? PAN_RIGHT : pan);
1352 }
1353
1354 static void
DoITTempo(UBYTE tempo)1355 DoITTempo (UBYTE tempo)
1356 {
1357 SWORD temp = mp.newbpm;
1358
1359 if (mp.patdly2)
1360 return;
1361
1362 if (tempo & 0x10)
1363 temp += (tempo & 0x0f);
1364 else
1365 temp -= tempo;
1366
1367 mp.newbpm = (temp > 255) ? 255 : (temp < 1 ? 1 : temp);
1368 }
1369
1370 static void
DoITVibrato(void)1371 DoITVibrato (void)
1372 {
1373 UBYTE q;
1374 UWORD temp = 0;
1375
1376 q = (a->vibpos >> 2) & 0x1f;
1377
1378 switch (a->wavecontrol & 3)
1379 {
1380 case 0: /* sine */
1381 temp = VibratoTable[q];
1382 break;
1383 case 1: /* square wave */
1384 temp = 255;
1385 break;
1386 case 2: /* ramp down */
1387 q <<= 3;
1388 if (a->vibpos < 0)
1389 q = 255 - q;
1390 temp = q;
1391 break;
1392 case 3: /* random */
1393 temp = getrandom (256);
1394 break;
1395 }
1396
1397 temp *= a->vibdepth;
1398 temp >>= 8;
1399 temp <<= 2;
1400
1401 if (a->vibpos >= 0)
1402 a->period = a->tmpperiod + temp;
1403 else
1404 a->period = a->tmpperiod - temp;
1405
1406 a->vibpos += a->vibspd;
1407 }
1408
1409 static void
DoITFineVibrato(void)1410 DoITFineVibrato (void)
1411 {
1412 UBYTE q;
1413 UWORD temp = 0;
1414
1415 q = (a->vibpos >> 2) & 0x1f;
1416
1417 switch (a->wavecontrol & 3)
1418 {
1419 case 0: /* sine */
1420 temp = VibratoTable[q];
1421 break;
1422 case 1: /* square wave */
1423 temp = 255;
1424 break;
1425 case 2: /* ramp down */
1426 q <<= 3;
1427 if (a->vibpos < 0)
1428 q = 255 - q;
1429 temp = q;
1430 break;
1431 case 3: /* random */
1432 temp = getrandom (256);
1433 break;
1434 }
1435
1436 temp *= a->vibdepth;
1437 temp >>= 8;
1438
1439 if (a->vibpos >= 0)
1440 a->period = a->tmpperiod + temp;
1441 else
1442 a->period = a->tmpperiod - temp;
1443
1444 a->vibpos += a->vibspd;
1445 }
1446
1447 static void
DoITTremor(UBYTE inf)1448 DoITTremor (UBYTE inf)
1449 {
1450 UBYTE on, off;
1451
1452 if (inf)
1453 a->s3mtronof = inf;
1454 else
1455 {
1456 inf = a->s3mtronof;
1457 if (!inf)
1458 return;
1459 }
1460
1461 if (!mp.vbtick)
1462 return;
1463
1464 on = (inf >> 4);
1465 off = (inf & 0xf);
1466
1467 a->s3mtremor %= (on + off);
1468 a->volume = (a->s3mtremor < on) ? a->tmpvolume : 0;
1469 a->s3mtremor++;
1470 }
1471
1472 static void
DoITPanbrello(void)1473 DoITPanbrello (void)
1474 {
1475 UBYTE q;
1476 SLONG temp = 0;
1477
1478 q = a->panbpos;
1479
1480 switch (a->panbwave)
1481 {
1482 case 0: /* sine */
1483 temp = PanbrelloTable[q];
1484 break;
1485 case 1: /* square wave */
1486 temp = (q < 0x80) ? 64 : 0;
1487 break;
1488 case 2: /* ramp down */
1489 q <<= 3;
1490 temp = q;
1491 break;
1492 case 3: /* random */
1493 if (a->panbpos >= a->panbspd)
1494 {
1495 a->panbpos = 0;
1496 temp = getrandom (256);
1497 }
1498 }
1499
1500 temp *= a->panbdepth;
1501 temp = (temp / 8) + pf->panning[mp.channel];
1502
1503 a->panning = (temp < PAN_LEFT) ? PAN_LEFT : (temp > PAN_RIGHT ? PAN_RIGHT : temp);
1504 a->panbpos += a->panbspd;
1505 }
1506
1507 static void
DoITToneSlide(void)1508 DoITToneSlide (void)
1509 {
1510 /* if we don't come from another note, ignore the slide and play the note
1511 as is */
1512 if (!a->oldnote)
1513 return;
1514
1515 if (mp.vbtick)
1516 {
1517 int dist;
1518
1519 /* We have to slide a->period towards a->wantedperiod, compute the
1520 difference between those two values */
1521 dist = a->period - a->wantedperiod;
1522
1523 /* if they are equal or if portamentospeed is too big... */
1524 if ((!dist) || ((a->portspeed << 2) > abs (dist)))
1525 /* ... make tmpperiod equal tperiod */
1526 a->tmpperiod = a->period = a->wantedperiod;
1527 else if (dist > 0)
1528 {
1529 a->tmpperiod -= a->portspeed << 2;
1530 a->period -= a->portspeed << 2; /* dist>0 slide up */
1531 }
1532 else
1533 {
1534 a->tmpperiod += a->portspeed << 2;
1535 a->period += a->portspeed << 2; /* dist<0 slide down */
1536 }
1537 }
1538 else
1539 a->tmpperiod = a->period;
1540 }
1541
1542 static void DoNNAEffects (UBYTE dat);
1543 /* Impulse/Scream Tracker Sxx effects.
1544 All Sxx effects share the same memory space. */
1545 static void
DoSSEffects(UBYTE dat)1546 DoSSEffects (UBYTE dat)
1547 {
1548 UBYTE inf, c;
1549
1550 inf = dat & 0xf;
1551 c = dat >> 4;
1552
1553 if (!dat)
1554 {
1555 c = a->sseffect;
1556 inf = a->ssdata;
1557 }
1558 else
1559 {
1560 a->sseffect = c;
1561 a->ssdata = inf;
1562 }
1563
1564 switch (c)
1565 {
1566 case SS_GLISSANDO: /* S1x set glissando voice */
1567 DoEEffects (0x30 | inf);
1568 break;
1569 case SS_FINETUNE: /* S2x set finetune */
1570 DoEEffects (0x50 | inf);
1571 break;
1572 case SS_VIBWAVE: /* S3x set vibrato waveform */
1573 DoEEffects (0x40 | inf);
1574 break;
1575 case SS_TREMWAVE: /* S4x set tremolo waveform */
1576 DoEEffects (0x70 | inf);
1577 break;
1578 case SS_PANWAVE: /* S5x panbrello */
1579 a->panbwave = inf;
1580 break;
1581 case SS_FRAMEDELAY: /* S6x delay x number of frames (patdly) */
1582 DoEEffects (0xe0 | inf);
1583 break;
1584 case SS_S7EFFECTS: /* S7x instrument / NNA commands */
1585 DoNNAEffects (inf);
1586 break;
1587 case SS_PANNING: /* S8x set panning position */
1588 DoEEffects (0x80 | inf);
1589 break;
1590 case SS_SURROUND: /* S9x set surround sound */
1591 a->panning = pf->panning[mp.channel] = PAN_SURROUND;
1592 break;
1593 case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
1594 if (!mp.vbtick)
1595 {
1596 a->hioffset = inf << 16;
1597 a->start = a->hioffset | a->soffset;
1598
1599 if ((a->s) && (a->start > a->s->length))
1600 a->start = a->s->flags & (SF_LOOP | SF_BIDI) ? a->s->loopstart : a->s->length;
1601 }
1602 break;
1603 case SS_PATLOOP: /* SBx pattern loop */
1604 DoEEffects (0x60 | inf);
1605 break;
1606 case SS_NOTECUT: /* SCx notecut */
1607 DoEEffects (0xC0 | inf);
1608 break;
1609 case SS_NOTEDELAY: /* SDx notedelay */
1610 DoEEffects (0xD0 | inf);
1611 break;
1612 case SS_PATDELAY: /* SEx patterndelay */
1613 DoEEffects (0xE0 | inf);
1614 break;
1615 }
1616 }
1617
1618 /* Impulse Tracker Volume/Pan Column effects.
1619 All volume/pan column effects share the same memory space. */
1620 static void
DoVolEffects(UBYTE c)1621 DoVolEffects (UBYTE c)
1622 {
1623 UBYTE inf = UniGetByte ();
1624
1625 if ((!c) && (!inf))
1626 {
1627 c = a->voleffect;
1628 inf = a->voldata;
1629 }
1630 else
1631 {
1632 a->voleffect = c;
1633 a->voldata = inf;
1634 }
1635
1636 if (c)
1637 switch (c)
1638 {
1639 case VOL_VOLUME:
1640 if (mp.vbtick)
1641 break;
1642 if (inf > 64)
1643 inf = 64;
1644 a->tmpvolume = inf;
1645 break;
1646 case VOL_PANNING:
1647 a->panning = /*pf->panning[mp.channel]= */ inf;
1648 break;
1649 case VOL_VOLSLIDE:
1650 DoS3MVolSlide (inf);
1651 break;
1652 case VOL_PITCHSLIDEDN:
1653 if (a->period)
1654 DoS3MSlideDn (inf);
1655 break;
1656 case VOL_PITCHSLIDEUP:
1657 if (a->period)
1658 DoS3MSlideUp (inf);
1659 break;
1660 case VOL_PORTAMENTO:
1661 if (inf)
1662 a->slidespeed = inf;
1663 if (a->period)
1664 {
1665 if ((!mp.vbtick) || (a->newsamp))
1666 {
1667 a->kick = KICK_NOTE;
1668 a->start = -1;
1669 }
1670 else
1671 a->kick = (a->kick == KICK_NOTE) ? KICK_ENV : KICK_ABSENT;
1672 DoITToneSlide ();
1673 a->ownper = 1;
1674 }
1675 break;
1676 case VOL_VIBRATO:
1677 if (!mp.vbtick)
1678 {
1679 if (inf & 0x0f)
1680 a->vibdepth = inf & 0xf;
1681 if (inf & 0xf0)
1682 a->vibspd = (inf & 0xf0) >> 2;
1683 }
1684 if (a->period)
1685 {
1686 DoITVibrato ();
1687 a->ownper = 1;
1688 }
1689 break;
1690 }
1691 }
1692
1693 /*========== UltraTracker effects */
1694
1695 static void
DoULTSampleOffset(void)1696 DoULTSampleOffset (void)
1697 {
1698 UWORD offset = UniGetWord ();
1699
1700 if (offset)
1701 a->ultoffset = offset;
1702
1703 a->start = a->ultoffset << 2;
1704 if ((a->s) && (a->start > a->s->length))
1705 a->start = a->s->flags & (SF_LOOP | SF_BIDI) ? a->s->loopstart : a->s->length;
1706 }
1707
1708 /*========== OctaMED effects */
1709
1710 static void
DoMEDSpeed(void)1711 DoMEDSpeed (void)
1712 {
1713 UWORD speed = UniGetWord ();
1714
1715 mp.newbpm = speed;
1716 }
1717
1718 /*========== General player functions */
1719
1720 static void
pt_playeffects(void)1721 pt_playeffects (void)
1722 {
1723 UBYTE dat, c, oldc = 0;
1724
1725 while ((c = UniGetByte ()))
1726 {
1727 int oldsliding = a->sliding;
1728
1729 a->sliding = 0;
1730
1731 /* libunimod doesn't *quite* do Ultimate Soundtracker portas correctly */
1732 if (strcmp(of.modtype, "Ultimate Soundtracker") == 0)
1733 {
1734 if (c == 5 && oldc == 4)
1735 {
1736 oldc = 5;
1737 a->sliding = oldsliding;
1738 UniSkipOpcode (c);
1739 continue;
1740 }
1741 oldc = c;
1742 if (c == 3 || c == 4)
1743 c++;
1744 }
1745
1746 switch (c)
1747 {
1748 case UNI_PTEFFECT0:
1749 dat = UniGetByte ();
1750 if (!mp.vbtick)
1751 {
1752 if ((!dat) && (pf->flags & UF_ARPMEM))
1753 dat = a->arpmem;
1754 else
1755 a->arpmem = dat;
1756 }
1757 if (a->period)
1758 DoArpeggio (a->arpmem);
1759 break;
1760 case UNI_PTEFFECT1:
1761 dat = UniGetByte ();
1762 if ((!mp.vbtick) && (dat))
1763 a->slidespeed = (UWORD) dat << 2;
1764 if (a->period)
1765 if (mp.vbtick)
1766 a->tmpperiod -= a->slidespeed;
1767 break;
1768 case UNI_PTEFFECT2:
1769 dat = UniGetByte ();
1770 if ((!mp.vbtick) && (dat))
1771 a->slidespeed = (UWORD) dat << 2;
1772 if (a->period)
1773 if (mp.vbtick)
1774 a->tmpperiod += a->slidespeed;
1775 break;
1776 case UNI_PTEFFECT3:
1777 dat = UniGetByte ();
1778 if ((!mp.vbtick) && (dat))
1779 a->portspeed = (UWORD) dat << 2;
1780 if (a->period)
1781 {
1782 if (!a->fadevol)
1783 a->kick = (a->kick == KICK_NOTE) ? KICK_NOTE : KICK_KEYOFF;
1784 else
1785 a->kick = (a->kick == KICK_NOTE) ? KICK_ENV : KICK_ABSENT;
1786 DoToneSlide ();
1787 a->ownper = 1;
1788 }
1789 break;
1790 case UNI_PTEFFECT4:
1791 case UNI_XMEFFECT4:
1792 dat = UniGetByte ();
1793 if (!mp.vbtick)
1794 {
1795 if (dat & 0x0f)
1796 a->vibdepth = dat & 0xf;
1797 if (dat & 0xf0)
1798 a->vibspd = (dat & 0xf0) >> 2;
1799 }
1800 else if (a->period)
1801 {
1802 DoVibrato ();
1803 a->ownper = 1;
1804 }
1805 break;
1806 case UNI_PTEFFECT5:
1807 dat = UniGetByte ();
1808 if (a->period)
1809 {
1810 if (!a->fadevol)
1811 a->kick = (a->kick == KICK_NOTE) ? KICK_NOTE : KICK_KEYOFF;
1812 else
1813 a->kick = (a->kick == KICK_NOTE) ? KICK_ENV : KICK_ABSENT;
1814 DoToneSlide ();
1815 a->ownper = 1;
1816 }
1817 DoVolSlide (dat);
1818 break;
1819 case UNI_PTEFFECT6:
1820 dat = UniGetByte ();
1821 if ((a->period) && (mp.vbtick))
1822 {
1823 DoVibrato ();
1824 a->ownper = 1;
1825 }
1826 DoVolSlide (dat);
1827 break;
1828 case UNI_PTEFFECT7:
1829 dat = UniGetByte ();
1830 if (!mp.vbtick)
1831 {
1832 if (dat & 0x0f)
1833 a->trmdepth = dat & 0xf;
1834 if (dat & 0xf0)
1835 a->trmspd = (dat & 0xf0) >> 2;
1836 }
1837 if (a->period)
1838 {
1839 DoTremolo ();
1840 a->ownvol = 1;
1841 }
1842 break;
1843 case UNI_PTEFFECT8:
1844 dat = UniGetByte ();
1845 a->panning = pf->panning[mp.channel] = dat;
1846 break;
1847 case UNI_PTEFFECT9:
1848 dat = UniGetByte ();
1849 if (!mp.vbtick)
1850 {
1851 if (dat)
1852 a->soffset = (UWORD) dat << 8;
1853 a->start = a->hioffset | a->soffset;
1854
1855 if ((a->s) && (a->start > a->s->length))
1856 a->start = a->s->flags & (SF_LOOP | SF_BIDI) ? a->s->loopstart : a->s->length;
1857 }
1858 break;
1859 case UNI_PTEFFECTA:
1860 DoVolSlide (UniGetByte ());
1861 break;
1862 case UNI_PTEFFECTB:
1863 dat = UniGetByte ();
1864 if ((mp.vbtick) || (mp.patdly2))
1865 break;
1866 /* Vincent Voois uses a nasty trick in "Universal Bolero" */
1867 if (dat == mp.sngpos && mp.patbrk == mp.patpos)
1868 break;
1869 if ((!mp.patbrk) && ((dat < mp.sngpos) ||
1870 ((mp.sngpos == pf->numpos - 1) && (!mp.patbrk)) ||
1871 ((dat == mp.sngpos) && (pf->flags & UF_NOWRAP))))
1872 {
1873 /* if we don't loop, better not to skip the end of the
1874 pattern, after all... so:
1875 mp.patbrk=0; */
1876 mp.posjmp = 3;
1877 }
1878 else
1879 {
1880 /* if we were fading, adjust... */
1881 if (mp.sngpos == (pf->numpos - 1))
1882 mp.volume = pf->initvolume > 128 ? 128 : pf->initvolume;
1883
1884 mp.sngpos = dat;
1885 mp.posjmp = 2;
1886 mp.patpos = 0;
1887 }
1888 break;
1889 case UNI_PTEFFECTC:
1890 dat = UniGetByte ();
1891 if (mp.vbtick)
1892 break;
1893 if (dat == (UBYTE) - 1)
1894 a->anote = dat = 0; /* note cut */
1895 else if (dat > 64)
1896 dat = 64;
1897 a->tmpvolume = dat;
1898 break;
1899 case UNI_PTEFFECTD:
1900 dat = UniGetByte ();
1901 if ((mp.vbtick) || (mp.patdly2))
1902 break;
1903 if ((pf->positions[mp.sngpos] != 255) &&
1904 (dat > pf->pattrows[pf->positions[mp.sngpos]]))
1905 dat = pf->pattrows[pf->positions[mp.sngpos]];
1906 mp.patbrk = dat;
1907 if (!mp.posjmp)
1908 {
1909 /* don't ask me to explain this code - it makes
1910 * backwards.s3m and children.xm (heretic's version) play
1911 * correctly, among others. Take that for granted, or write
1912 * the page of comments yourself... you might need some
1913 * aspirin - Miod */
1914 if ((mp.sngpos == pf->numpos - 1) && (dat) &&
1915 ((pf->positions[mp.sngpos] == (pf->numpat - 1)
1916 && (pf->flags & UF_NOWRAP))))
1917 {
1918 /* printf("%d -- Pattern 0!\n", __LINE__); */
1919 mp.sngpos = 0;
1920 mp.posjmp = 2;
1921 }
1922 else
1923 mp.posjmp = 3;
1924 }
1925 break;
1926 case UNI_PTEFFECTE:
1927 DoEEffects (UniGetByte ());
1928 break;
1929 case UNI_PTEFFECTF:
1930 dat = UniGetByte ();
1931 if (mp.vbtick || mp.patdly2)
1932 break;
1933 if (dat > 0x20)
1934 mp.newbpm = dat;
1935 else if (dat)
1936 {
1937 mp.sngspd = (dat > 32) ? 32 : dat;
1938 mp.vbtick = 0;
1939 }
1940 break;
1941 case UNI_S3MEFFECTA:
1942 DoS3MSpeed (UniGetByte ());
1943 break;
1944 case UNI_S3MEFFECTD:
1945 DoS3MVolSlide (UniGetByte ());
1946 break;
1947 case UNI_S3MEFFECTE:
1948 dat = UniGetByte ();
1949 if (a->period)
1950 DoS3MSlideDn (dat);
1951 break;
1952 case UNI_S3MEFFECTF:
1953 dat = UniGetByte ();
1954 if (a->period)
1955 DoS3MSlideUp (dat);
1956 break;
1957 case UNI_S3MEFFECTI:
1958 DoS3MTremor (UniGetByte ());
1959 a->ownvol = 1;
1960 break;
1961 case UNI_S3MEFFECTQ:
1962 dat = UniGetByte ();
1963 if (a->period)
1964 DoS3MRetrig (dat);
1965 break;
1966 case UNI_S3MEFFECTR:
1967 dat = UniGetByte ();
1968 if (!mp.vbtick)
1969 {
1970 if (dat & 0x0f)
1971 a->trmdepth = dat & 0xf;
1972 if (dat & 0xf0)
1973 a->trmspd = (dat & 0xf0) >> 2;
1974 }
1975 DoS3MTremolo ();
1976 a->ownvol = 1;
1977 break;
1978 case UNI_S3MEFFECTT:
1979 DoS3MTempo (UniGetByte ());
1980 break;
1981 case UNI_S3MEFFECTU:
1982 dat = UniGetByte ();
1983 if (!mp.vbtick)
1984 {
1985 if (dat & 0x0f)
1986 a->vibdepth = dat & 0xf;
1987 if (dat & 0xf0)
1988 a->vibspd = (dat & 0xf0) >> 2;
1989 }
1990 else if (a->period)
1991 {
1992 DoS3MFineVibrato ();
1993 a->ownper = 1;
1994 }
1995 break;
1996 case UNI_KEYOFF:
1997 a->keyoff |= KEY_OFF;
1998 if ((!(a->volflg & EF_ON)) || (a->volflg & EF_LOOP))
1999 a->keyoff = KEY_KILL;
2000 break;
2001 case UNI_KEYFADE:
2002 dat = UniGetByte ();
2003 if ((mp.vbtick >= dat) || (mp.vbtick == mp.sngspd - 1))
2004 {
2005 a->keyoff = KEY_KILL;
2006 if (!(a->volflg & EF_ON))
2007 a->fadevol = 0;
2008 }
2009 break;
2010 case UNI_VOLEFFECTS:
2011 DoVolEffects (UniGetByte ());
2012 break;
2013 case UNI_XMEFFECTA:
2014 DoXMVolSlide (UniGetByte ());
2015 break;
2016 case UNI_XMEFFECTE1: /* XM fineslide up */
2017 if (mp.vbtick)
2018 break;
2019 dat = UniGetByte ();
2020 if (!mp.vbtick)
2021 {
2022 if (dat)
2023 a->fportupspd = dat;
2024 if (a->period)
2025 a->tmpperiod -= (a->fportupspd << 2);
2026 }
2027 break;
2028 case UNI_XMEFFECTE2: /* XM fineslide dn */
2029 if (mp.vbtick)
2030 break;
2031 dat = UniGetByte ();
2032 if (!mp.vbtick)
2033 {
2034 if (dat)
2035 a->fportdnspd = dat;
2036 if (a->period)
2037 a->tmpperiod += (a->fportdnspd << 2);
2038 }
2039 break;
2040 case UNI_XMEFFECTEA: /* fine volume slide up */
2041 if (mp.vbtick)
2042 break;
2043 dat = UniGetByte ();
2044 if (dat)
2045 a->fslideupspd = dat;
2046 a->tmpvolume += a->fslideupspd;
2047 if (a->tmpvolume > 64)
2048 a->tmpvolume = 64;
2049 break;
2050 case UNI_XMEFFECTEB: /* fine volume slide dn */
2051 if (mp.vbtick)
2052 break;
2053 dat = UniGetByte ();
2054 if (dat)
2055 a->fslidednspd = dat;
2056 a->tmpvolume -= a->fslidednspd;
2057 if (a->tmpvolume < 0)
2058 a->tmpvolume = 0;
2059 break;
2060 case UNI_XMEFFECTG:
2061 mp.volume = UniGetByte () << 1;
2062 if (mp.volume > 128)
2063 mp.volume = 128;
2064 break;
2065 case UNI_XMEFFECTH:
2066 DoXMGlobalSlide (UniGetByte ());
2067 break;
2068 case UNI_XMEFFECTL:
2069 dat = UniGetByte ();
2070 if ((!mp.vbtick) && (a->i))
2071 {
2072 UWORD points;
2073 INSTRUMENT *i = a->i;
2074 MP_VOICE *aout;
2075
2076 if ((aout = a->slave))
2077 {
2078 if (aout->venv.env) {
2079 points = i->volenv[i->volpts - 1].pos;
2080 aout->venv.p = aout->venv.env[(dat > points) ? points : dat].pos;
2081 }
2082 if (aout->penv.env) {
2083 points = i->panenv[i->panpts - 1].pos;
2084 aout->penv.p = aout->penv.env[(dat > points) ? points : dat].pos;
2085 }
2086 }
2087 }
2088 break;
2089 case UNI_XMEFFECTP:
2090 dat = UniGetByte ();
2091 DoXMPanSlide (dat);
2092 break;
2093 case UNI_XMEFFECTX1:
2094 if (mp.vbtick)
2095 break;
2096 dat = UniGetByte ();
2097 if (dat)
2098 a->ffportupspd = dat;
2099 else
2100 dat = a->ffportupspd;
2101 if (a->period)
2102 {
2103 DoXMExtraFineSlideUp (dat);
2104 a->ownper = 1;
2105 }
2106 break;
2107 case UNI_XMEFFECTX2:
2108 if (mp.vbtick)
2109 break;
2110 dat = UniGetByte ();
2111 if (dat)
2112 a->ffportdnspd = dat;
2113 else
2114 dat = a->ffportdnspd;
2115 if (a->period)
2116 {
2117 DoXMExtraFineSlideDown (dat);
2118 a->ownper = 1;
2119 }
2120 break;
2121 case UNI_ITEFFECTG:
2122 dat = UniGetByte ();
2123 if (dat)
2124 {
2125 a->portspeed = dat;
2126 }
2127 if (a->period)
2128 {
2129 if ((!mp.vbtick) && (a->newsamp))
2130 {
2131 a->kick = KICK_NOTE;
2132 a->start = -1;
2133 }
2134 else
2135 a->kick = (a->kick == KICK_NOTE) ? KICK_ENV : KICK_ABSENT;
2136 DoITToneSlide ();
2137 a->ownper = 1;
2138 }
2139 break;
2140 case UNI_ITEFFECTH: /* IT vibrato */
2141 dat = UniGetByte ();
2142 if (!mp.vbtick)
2143 {
2144 if (dat & 0x0f)
2145 a->vibdepth = dat & 0xf;
2146 if (dat & 0xf0)
2147 a->vibspd = (dat & 0xf0) >> 2;
2148 }
2149 if (a->period)
2150 {
2151 DoITVibrato ();
2152 a->ownper = 1;
2153 }
2154 break;
2155 case UNI_ITEFFECTI: /* IT tremor */
2156 DoITTremor (UniGetByte ());
2157 a->ownvol = 1;
2158 break;
2159 case UNI_ITEFFECTM:
2160 a->chanvol = UniGetByte ();
2161 if (a->chanvol > 64)
2162 a->chanvol = 64;
2163 else if (a->chanvol < 0)
2164 a->chanvol = 0;
2165 break;
2166 case UNI_ITEFFECTN: /* slide / fineslide channel volume */
2167 DoITChanVolSlide (UniGetByte ());
2168 break;
2169 case UNI_ITEFFECTP: /* slide / fineslide channel panning */
2170 dat = UniGetByte ();
2171 DoITPanSlide (dat);
2172 break;
2173 case UNI_ITEFFECTT: /* slide / fineslide tempo */
2174 DoITTempo (UniGetByte ());
2175 break;
2176 case UNI_ITEFFECTU: /* fine vibrato */
2177 dat = UniGetByte ();
2178 if (!mp.vbtick)
2179 {
2180 if (dat & 0x0f)
2181 a->vibdepth = dat & 0xf;
2182 if (dat & 0xf0)
2183 a->vibspd = (dat & 0xf0) >> 2;
2184 }
2185 if (a->period)
2186 {
2187 DoITFineVibrato ();
2188 a->ownper = 1;
2189 }
2190 break;
2191 case UNI_ITEFFECTW: /* slide / fineslide global volume */
2192 DoITGlobalSlide (UniGetByte ());
2193 break;
2194 case UNI_ITEFFECTY: /* panbrello */
2195 dat = UniGetByte ();
2196 if (!mp.vbtick)
2197 {
2198 if (dat & 0x0f)
2199 a->panbdepth = (dat & 0xf);
2200 if (dat & 0xf0)
2201 a->panbspd = (dat & 0xf0) >> 4;
2202 }
2203 DoITPanbrello ();
2204 break;
2205 case UNI_ITEFFECTS0:
2206 DoSSEffects (UniGetByte ());
2207 break;
2208 case UNI_ITEFFECTZ:
2209 /* FIXME not yet implemented */
2210 UniSkipOpcode (UNI_ITEFFECTZ);
2211 break;
2212 case UNI_ULTEFFECT9:
2213 DoULTSampleOffset ();
2214 break;
2215 case UNI_MEDSPEED:
2216 DoMEDSpeed ();
2217 break;
2218 case UNI_MEDEFFECTF1:
2219 DoEEffects (0x90 | (mp.sngspd / 2));
2220 break;
2221 case UNI_MEDEFFECTF2:
2222 DoEEffects (0xd0 | (mp.sngspd / 2));
2223 break;
2224 case UNI_MEDEFFECTF3:
2225 DoEEffects (0x90 | (mp.sngspd / 3));
2226 break;
2227 /* case UNI_NOTE: */
2228 /* case UNI_INSTRUMENT: */
2229 default:
2230 a->sliding = oldsliding;
2231 UniSkipOpcode (c);
2232 break;
2233 }
2234 }
2235 }
2236
2237 static void
DoNNAEffects(UBYTE dat)2238 DoNNAEffects (UBYTE dat)
2239 {
2240 int t;
2241 MP_VOICE *aout;
2242
2243 dat &= 0xf;
2244 aout = (a->slave) ? a->slave : NULL;
2245
2246 switch (dat)
2247 {
2248 case 0x0: /* past note cut */
2249 for (t = 0; t < MOD_NUM_VOICES; t++)
2250 if (mp.voice[t].master == a)
2251 mp.voice[t].fadevol = 0;
2252 break;
2253 case 0x1: /* past note off */
2254 for (t = 0; t < MOD_NUM_VOICES; t++)
2255 if (mp.voice[t].master == a)
2256 {
2257 mp.voice[t].keyoff |= KEY_OFF;
2258 if ((!(mp.voice[t].venv.flg & EF_ON)) ||
2259 (mp.voice[t].venv.flg & EF_LOOP))
2260 mp.voice[t].keyoff = KEY_KILL;
2261 }
2262 break;
2263 case 0x2: /* past note fade */
2264 for (t = 0; t < MOD_NUM_VOICES; t++)
2265 if (mp.voice[t].master == a)
2266 mp.voice[t].keyoff |= KEY_FADE;
2267 break;
2268 case 0x3: /* set NNA note cut */
2269 a->nna = (a->nna & ~NNA_MASK) | NNA_CUT;
2270 break;
2271 case 0x4: /* set NNA note continue */
2272 a->nna = (a->nna & ~NNA_MASK) | NNA_CONTINUE;
2273 break;
2274 case 0x5: /* set NNA note off */
2275 a->nna = (a->nna & ~NNA_MASK) | NNA_OFF;
2276 break;
2277 case 0x6: /* set NNA note fade */
2278 a->nna = (a->nna & ~NNA_MASK) | NNA_FADE;
2279 break;
2280 case 0x7: /* disable volume envelope */
2281 if (aout)
2282 aout->volflg &= ~EF_ON;
2283 break;
2284 case 0x8: /* enable volume envelope */
2285 if (aout)
2286 aout->volflg |= EF_ON;
2287 break;
2288 case 0x9: /* disable panning envelope */
2289 if (aout)
2290 aout->panflg &= ~EF_ON;
2291 break;
2292 case 0xa: /* enable panning envelope */
2293 if (aout)
2294 aout->panflg |= EF_ON;
2295 break;
2296 case 0xb: /* disable pitch envelope */
2297 if (aout)
2298 aout->pitflg &= ~EF_ON;
2299 break;
2300 case 0xc: /* enable pitch envelope */
2301 if (aout)
2302 aout->pitflg |= EF_ON;
2303 break;
2304 }
2305 }
2306
2307 static void
pt_UpdateVoices()2308 pt_UpdateVoices ()
2309 {
2310 SWORD envpan, envvol, envpit;
2311 UWORD playperiod;
2312 SLONG vibval, vibdpt;
2313 ULONG tmpvol;
2314 BOOL kick_voice;
2315
2316 MP_VOICE *aout;
2317 INSTRUMENT *i;
2318 SAMPLE *s;
2319
2320 mp.totalchn = mp.realchn = 0;
2321 for (mp.channel = 0; mp.channel < MOD_NUM_VOICES; mp.channel++)
2322 {
2323 aout = &mp.voice[mp.channel];
2324 i = aout->i;
2325 s = aout->s;
2326
2327 if ((!s) || (!s->length))
2328 continue;
2329
2330 if (aout->period < 14 || aout->period > 50000)
2331 {
2332 Voice_Stop(mp.channel);
2333 continue;
2334 }
2335
2336 kick_voice = 0;
2337 if ((aout->kick == KICK_NOTE) || (aout->kick == KICK_KEYOFF))
2338 {
2339 kick_voice = 1;
2340 aout->fadevol = 32768;
2341 aout->aswppos = 0;
2342 }
2343
2344 /* check for a dead note (fadevol=0) */
2345 if (!aout->fadevol || kick_voice)
2346 Voice_Stop (mp.channel);
2347
2348 if (i && ((aout->kick == KICK_NOTE) || (aout->kick == KICK_ENV)))
2349 {
2350 StartEnvelope (&aout->venv, aout->volflg, i->volpts, i->volsusbeg,
2351 i->volsusend, i->volbeg, i->volend, i->volenv, aout->keyoff);
2352 StartEnvelope (&aout->penv, aout->panflg, i->panpts, i->pansusbeg,
2353 i->pansusend, i->panbeg, i->panend, i->panenv, aout->keyoff);
2354 StartEnvelope (&aout->cenv, aout->pitflg, i->pitpts, i->pitsusbeg,
2355 i->pitsusend, i->pitbeg, i->pitend, i->pitenv, aout->keyoff);
2356 if (aout->cenv.flg & EF_ON)
2357 aout->masterperiod = GetPeriod ((UWORD) aout->note << 1, aout->master->speed);
2358 }
2359 aout->kick = KICK_ABSENT;
2360
2361 envvol = (!(aout->volflg & EF_ON)) ? 256 :
2362 ProcessEnvelope (&aout->venv, 256, aout->keyoff);
2363 envpan = (!(aout->panflg & EF_ON)) ? PAN_CENTER :
2364 ProcessEnvelope (&aout->penv, PAN_CENTER, aout->keyoff);
2365 envpit = (!(aout->pitflg & EF_ON)) ? 32 :
2366 ProcessEnvelope (&aout->cenv, 32, aout->keyoff);
2367
2368 tmpvol = aout->fadevol; /* max 32768 */
2369 tmpvol *= aout->chanvol; /* * max 64 */
2370 tmpvol *= aout->volume; /* * max 256 */
2371 tmpvol /= 16384L; /* tmpvol is max 32768 */
2372 aout->totalvol = tmpvol >> 2; /* totalvolume used to determine samplevolume */
2373 tmpvol *= envvol; /* * max 256 */
2374 tmpvol *= mp.volume; /* * max 128 */
2375 tmpvol /= 4194304UL;
2376
2377 Voice_SetVolume (mp.channel, tmpvol);
2378 if ((tmpvol) && (aout->master) && (aout->master->slave == aout))
2379 mp.realchn++;
2380 mp.totalchn++;
2381
2382 if (aout->panning == PAN_SURROUND)
2383 Voice_SetPanning (mp.channel, PAN_SURROUND);
2384 else if (aout->penv.flg & EF_ON)
2385 Voice_SetPanning (mp.channel, DoPan (envpan, aout->panning));
2386 else
2387 Voice_SetPanning (mp.channel, aout->panning);
2388
2389 if (aout->period && s->vibdepth)
2390 switch (s->vibtype)
2391 {
2392 case 0:
2393 vibval = avibtab[aout->avibpos & 127];
2394 if (aout->avibpos & 0x80)
2395 vibval = -vibval;
2396 break;
2397 case 1:
2398 vibval = 64;
2399 if (aout->avibpos & 0x80)
2400 vibval = -vibval;
2401 break;
2402 case 2:
2403 vibval = 63 - (((aout->avibpos + 128) & 255) >> 1);
2404 break;
2405 default:
2406 vibval = (((aout->avibpos + 128) & 255) >> 1) - 64;
2407 break;
2408 }
2409 else
2410 vibval = 0;
2411
2412 if (s->vibflags & AV_IT)
2413 {
2414 if ((aout->aswppos >> 8) < s->vibdepth)
2415 {
2416 aout->aswppos += s->vibsweep;
2417 vibdpt = aout->aswppos;
2418 }
2419 else
2420 vibdpt = s->vibdepth << 8;
2421 vibval = (vibval * vibdpt) >> 16;
2422 if (aout->mflag)
2423 {
2424 if (!(pf->flags & UF_LINEAR))
2425 vibval >>= 1;
2426 aout->period -= vibval;
2427 }
2428 }
2429 else
2430 {
2431 /* do XM style auto-vibrato */
2432 if (!(aout->keyoff & KEY_OFF))
2433 {
2434 if (aout->aswppos < s->vibsweep)
2435 {
2436 vibdpt = (aout->aswppos * s->vibdepth) / s->vibsweep;
2437 aout->aswppos++;
2438 }
2439 else
2440 vibdpt = s->vibdepth;
2441 }
2442 else
2443 {
2444 /* keyoff -> depth becomes 0 if final depth wasn't reached or
2445 stays at final level if depth WAS reached */
2446 if (aout->aswppos >= s->vibsweep)
2447 vibdpt = s->vibdepth;
2448 else
2449 vibdpt = 0;
2450 }
2451 vibval = (vibval * vibdpt) >> 8;
2452 aout->period -= vibval;
2453 }
2454
2455 /* update vibrato position */
2456 aout->avibpos = (aout->avibpos + s->vibrate) & 0xff;
2457
2458 /* process pitch envelope */
2459 playperiod = aout->period;
2460
2461 if ((aout->pitflg & EF_ON) && (envpit != 32))
2462 {
2463 long p1;
2464
2465 envpit -= 32;
2466 if ((aout->note << 1) + envpit <= 0)
2467 envpit = -(aout->note << 1);
2468
2469 p1 = GetPeriod (((UWORD) aout->note << 1) + envpit, aout->master->speed) - aout->masterperiod;
2470 if (p1 > 0)
2471 {
2472 if ((UWORD) (playperiod + p1) <= playperiod)
2473 {
2474 p1 = 0;
2475 aout->keyoff |= KEY_OFF;
2476 }
2477 }
2478 else if (p1 < 0)
2479 {
2480 if ((UWORD) (playperiod + p1) >= playperiod)
2481 {
2482 p1 = 0;
2483 aout->keyoff |= KEY_OFF;
2484 }
2485 }
2486 playperiod += p1;
2487 }
2488
2489 if (!aout->fadevol)
2490 { /* check for a dead note (fadevol=0) */
2491 mp.totalchn--;
2492 if ((tmpvol) && (aout->master) && (aout->master->slave == aout))
2493 mp.realchn--;
2494 }
2495 else
2496 {
2497 Voice_SetPeriod (mp.channel,
2498 getAmigaPeriod (pf->flags, playperiod));
2499
2500 if (kick_voice)
2501 Voice_Play (mp.channel, s, (aout->start == -1) ? ((s->flags & SF_UST_LOOP) ? s->loopstart : 0) : aout->start);
2502
2503 /* if keyfade, start substracting fadeoutspeed from fadevol: */
2504 if ((i) && (aout->keyoff & KEY_FADE))
2505 {
2506 if (aout->fadevol >= i->volfade)
2507 aout->fadevol -= i->volfade;
2508 else
2509 aout->fadevol = 0;
2510 }
2511 }
2512
2513 if (mp.bpm != mp.newbpm || mp.sngspd != mp.oldsngspd) {
2514 mp.bpm = mp.newbpm;
2515 mp.oldsngspd = mp.sngspd;
2516 Voice_NewTempo(mp.bpm, mp.sngspd);
2517 }
2518 }
2519 }
2520
2521 /* Handles new notes or instruments */
2522 static void
pt_Notes(void)2523 pt_Notes (void)
2524 {
2525 UBYTE c, inst;
2526 int tr, funky; /* funky is set to indicate note or instrument change */
2527
2528 for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++)
2529 {
2530 a = &mp.control[mp.channel];
2531
2532 if (mp.sngpos >= pf->numpos)
2533 {
2534 tr = pf->numtrk;
2535 mp.numrow = 0;
2536 }
2537 else
2538 {
2539 tr = pf->patterns[(pf->positions[mp.sngpos] * pf->numchn) + mp.channel];
2540 mp.numrow = pf->pattrows[pf->positions[mp.sngpos]];
2541 }
2542
2543 a->row = (tr < pf->numtrk) ? UniFindRow (pf->tracks[tr], mp.patpos) : NULL;
2544 a->newsamp = 0;
2545 if (!mp.vbtick)
2546 a->notedelay = 0;
2547
2548 if (!a->row)
2549 continue;
2550 UniSetRow (a->row);
2551 funky = 0;
2552
2553 while ((c = UniGetByte ()))
2554 switch (c)
2555 {
2556 case UNI_NOTE:
2557 funky |= 1;
2558 a->oldnote = a->anote, a->anote = UniGetByte ();
2559 a->kick = KICK_NOTE;
2560 a->start = -1;
2561 a->sliding = 0;
2562
2563 /* retrig tremolo and vibrato waves ? */
2564 if (!(a->wavecontrol & 0x80))
2565 a->trmpos = 0;
2566 if (!(a->wavecontrol & 0x08))
2567 a->vibpos = 0;
2568 if (!a->panbwave)
2569 a->panbpos = 0;
2570 break;
2571 case UNI_INSTRUMENT:
2572 inst = UniGetByte ();
2573 if (inst >= pf->numins)
2574 break; /* safety valve */
2575 funky |= 2;
2576 a->i = (pf->flags & UF_INST) ? &pf->instruments[inst] : NULL;
2577 a->retrig = 0;
2578 a->s3mtremor = 0;
2579 a->ultoffset = 0;
2580 a->sample = inst;
2581 break;
2582 default:
2583 UniSkipOpcode (c);
2584 break;
2585 }
2586
2587 if (funky)
2588 {
2589 INSTRUMENT *i;
2590 SAMPLE *s;
2591
2592 i = a->i;
2593 if (i)
2594 {
2595 if (i->samplenumber[a->anote] >= pf->numsmp)
2596 continue;
2597 s = &pf->samples[i->samplenumber[a->anote]];
2598 a->note = i->samplenote[a->anote];
2599 }
2600 else
2601 {
2602 a->note = a->anote;
2603 s = &pf->samples[a->sample];
2604 }
2605
2606 if (a->s != s)
2607 {
2608 a->s = s;
2609 a->newsamp = a->period;
2610 }
2611
2612 /* channel or instrument determined panning ? */
2613 a->panning = pf->panning[mp.channel];
2614 if (s->flags & SF_OWNPAN)
2615 a->panning = s->panning;
2616 else if ((i) && (i->flags & IF_OWNPAN))
2617 a->panning = i->panning;
2618
2619 a->data = s->data;
2620 a->speed = s->speed;
2621
2622 if (i)
2623 {
2624 if ((i->flags & IF_PITCHPAN)
2625 && (a->panning != PAN_SURROUND))
2626 {
2627 a->panning += ((a->anote - i->pitpancenter) * i->pitpansep) / 8;
2628 if (a->panning < PAN_LEFT)
2629 a->panning = PAN_LEFT;
2630 else if (a->panning > PAN_RIGHT)
2631 a->panning = PAN_RIGHT;
2632 }
2633 a->pitflg = i->pitflg;
2634 a->volflg = i->volflg;
2635 a->panflg = i->panflg;
2636 a->nna = i->nnatype;
2637 a->dca = i->dca;
2638 a->dct = i->dct;
2639 }
2640 else
2641 {
2642 a->pitflg = 0;
2643 a->volflg = 0;
2644 a->panflg = 0;
2645 a->nna = 0;
2646 a->dca = 0;
2647 a->dct = DCT_OFF;
2648 }
2649
2650 if (funky & 2) /* instrument change */
2651 {
2652 /* IT random volume variations: 0:8 bit fixed, and one bit for
2653 sign. */
2654 a->volume = a->tmpvolume = s->volume;
2655 if ((s) && (i))
2656 {
2657 if (i->rvolvar)
2658 {
2659 a->volume = a->tmpvolume = s->volume +
2660 ((s->volume * ((SLONG) i->rvolvar * (SLONG) getrandom (512)
2661 )) / 25600);
2662 if (a->volume < 0)
2663 a->volume = a->tmpvolume = 0;
2664 else if (a->volume > 64)
2665 a->volume = a->tmpvolume = 64;
2666 }
2667 if ((a->panning != PAN_SURROUND))
2668 {
2669 a->panning += ((a->panning * ((SLONG) i->rpanvar *
2670 (SLONG) getrandom (512))) / 25600);
2671 if (a->panning < PAN_LEFT)
2672 a->panning = PAN_LEFT;
2673 else if (a->panning > PAN_RIGHT)
2674 a->panning = PAN_RIGHT;
2675 }
2676 }
2677 }
2678
2679 a->wantedperiod = a->tmpperiod = GetPeriod ((UWORD) a->note << 1, a->speed);
2680 a->keyoff = KEY_KICK;
2681 }
2682 }
2683 }
2684
2685 /* Handles effects */
2686 static void
pt_EffectsPass1(void)2687 pt_EffectsPass1 (void)
2688 {
2689 MP_VOICE *aout;
2690
2691 for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++)
2692 {
2693 a = &mp.control[mp.channel];
2694
2695 if ((aout = a->slave))
2696 {
2697 a->fadevol = aout->fadevol;
2698 a->period = aout->period;
2699 if (a->kick == KICK_KEYOFF)
2700 a->keyoff = aout->keyoff;
2701 }
2702
2703 if (!a->row)
2704 continue;
2705 UniSetRow (a->row);
2706
2707 a->ownper = a->ownvol = 0;
2708 mp.explicitslides = 0;
2709 pt_playeffects ();
2710
2711 /* continue volume slide if necessary for XM and IT */
2712 if (pf->flags & UF_BGSLIDES)
2713 {
2714 if (!mp.explicitslides && a->sliding)
2715 DoS3MVolSlide(0);
2716 else if (a->tmpvolume)
2717 a->sliding = mp.explicitslides;
2718 }
2719
2720 if (!a->ownper)
2721 a->period = a->tmpperiod;
2722 if (!a->ownvol)
2723 a->volume = a->tmpvolume;
2724
2725 if (a->s)
2726 {
2727 if (a->i)
2728 a->outvolume = (a->volume * a->s->globvol * a->i->globvol) >> 10;
2729 else
2730 a->outvolume = (a->volume * a->s->globvol) >> 4;
2731 if (a->outvolume > 256)
2732 a->volume = 256;
2733 else if (a->outvolume < 0)
2734 a->outvolume = 0;
2735 }
2736 }
2737 }
2738
2739 /* NNA management */
2740 static void
pt_NNA(void)2741 pt_NNA (void)
2742 {
2743 for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++)
2744 {
2745 a = &mp.control[mp.channel];
2746
2747 if (a->kick == KICK_NOTE)
2748 {
2749 BOOL k = 0;
2750
2751 if (a->slave)
2752 {
2753 MP_VOICE *aout;
2754
2755 aout = a->slave;
2756 if (aout->nna & NNA_MASK)
2757 {
2758 /* Make sure the old MP_VOICE channel knows it has no
2759 master now ! */
2760 a->slave = NULL;
2761 /* assume the channel is taken by NNA */
2762 aout->mflag = 0;
2763
2764 switch (aout->nna)
2765 {
2766 case NNA_CONTINUE: /* continue note, do nothing */
2767 break;
2768 case NNA_OFF: /* note off */
2769 aout->keyoff |= KEY_OFF;
2770 if ((!(aout->volflg & EF_ON)) || (aout->volflg & EF_LOOP))
2771 aout->keyoff = KEY_KILL;
2772 break;
2773 case NNA_FADE:
2774 aout->keyoff |= KEY_FADE;
2775 break;
2776 }
2777 }
2778 }
2779
2780 if (a->dct != DCT_OFF)
2781 {
2782 int t;
2783
2784 for (t = 0; t < MOD_NUM_VOICES; t++)
2785 if ((!Voice_Stopped (t)) &&
2786 (mp.voice[t].masterchn == mp.channel) &&
2787 (a->sample == mp.voice[t].sample))
2788 {
2789 k = 0;
2790 switch (a->dct)
2791 {
2792 case DCT_NOTE:
2793 if (a->note == mp.voice[t].note)
2794 k = 1;
2795 break;
2796 case DCT_SAMPLE:
2797 if (a->data == mp.voice[t].data)
2798 k = 1;
2799 break;
2800 case DCT_INST:
2801 k = 1;
2802 break;
2803 }
2804 if (k)
2805 switch (a->dca)
2806 {
2807 case DCA_CUT:
2808 mp.voice[t].fadevol = 0;
2809 break;
2810 case DCA_OFF:
2811 mp.voice[t].keyoff |= KEY_OFF;
2812 if ((!(mp.voice[t].volflg & EF_ON)) ||
2813 (mp.voice[t].volflg & EF_LOOP))
2814 mp.voice[t].keyoff = KEY_KILL;
2815 break;
2816 case DCA_FADE:
2817 mp.voice[t].keyoff |= KEY_FADE;
2818 break;
2819 }
2820 }
2821 }
2822 } /* if (a->kick==KICK_NOTE) */
2823 }
2824 }
2825
2826 /* Setup module and NNA voices */
2827 static void
pt_SetupVoices(void)2828 pt_SetupVoices (void)
2829 {
2830 MP_VOICE *aout;
2831
2832 for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++)
2833 {
2834 a = &mp.control[mp.channel];
2835
2836 if (a->notedelay)
2837 continue;
2838 if (a->kick == KICK_NOTE)
2839 {
2840 /* if no channel was cut above, find an empty or quiet channel
2841 here */
2842 if (pf->flags & UF_NNA)
2843 {
2844 if (!a->slave)
2845 {
2846 int newchn;
2847
2848 if ((newchn = MP_FindEmptyChannel ()) != -1)
2849 a->slave = &mp.voice[a->slavechn = newchn];
2850 }
2851 }
2852 else
2853 a->slave = &mp.voice[a->slavechn = mp.channel];
2854
2855 /* assign parts of MP_VOICE only done for a KICK_NOTE */
2856 if ((aout = a->slave))
2857 {
2858 if (aout->mflag && aout->master)
2859 aout->master->slave = NULL;
2860 aout->master = a;
2861 a->slave = aout;
2862 aout->masterchn = mp.channel;
2863 aout->mflag = 1;
2864 }
2865 }
2866 else
2867 aout = a->slave;
2868
2869 if (aout)
2870 {
2871 aout->i = a->i;
2872 aout->s = a->s;
2873 aout->sample = a->sample;
2874 aout->data = a->data;
2875 aout->period = a->period;
2876 aout->panning = a->panning;
2877 aout->chanvol = a->chanvol;
2878 aout->fadevol = a->fadevol;
2879 aout->kick = a->kick;
2880 aout->start = a->start;
2881 aout->volflg = a->volflg;
2882 aout->panflg = a->panflg;
2883 aout->pitflg = a->pitflg;
2884 aout->volume = a->outvolume;
2885 aout->keyoff = a->keyoff;
2886 aout->note = a->note;
2887 aout->nna = a->nna;
2888 }
2889 a->kick = KICK_ABSENT;
2890 }
2891 }
2892
2893 /* second effect pass */
2894 static void
pt_EffectsPass2(void)2895 pt_EffectsPass2 (void)
2896 {
2897 UBYTE c;
2898
2899 for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++)
2900 {
2901 a = &mp.control[mp.channel];
2902
2903 if (!a->row)
2904 continue;
2905 UniSetRow (a->row);
2906
2907 while ((c = UniGetByte ()))
2908 if (c == UNI_ITEFFECTS0)
2909 {
2910 c = UniGetByte ();
2911 if ((c >> 4) == SS_S7EFFECTS)
2912 DoNNAEffects (c & 0xf);
2913 }
2914 else
2915 UniSkipOpcode (c);
2916 }
2917 }
2918
2919 static BOOL
HandleTick(void)2920 HandleTick (void)
2921 {
2922 if ((!pf) || (mp.sngpos >= pf->numpos))
2923 return 0;
2924
2925 if (++mp.vbtick >= mp.sngspd)
2926 {
2927 if (mp.pat_repcrazy)
2928 mp.pat_repcrazy = 0; /* play 2 times row 0 */
2929 else
2930 mp.patpos++;
2931 mp.vbtick = 0;
2932
2933 /* process pattern-delay. mp.patdly2 is the counter and mp.patdly is
2934 the command memory. */
2935 if (mp.patdly)
2936 mp.patdly2 = mp.patdly, mp.patdly = 0;
2937 if (mp.patdly2)
2938 {
2939 /* patterndelay active */
2940 if (--mp.patdly2)
2941 /* so turn back mp.patpos by 1 */
2942 if (mp.patpos)
2943 mp.patpos--;
2944 }
2945
2946 /* do we have to get a new patternpointer ? (when mp.patpos reaches the
2947 pattern size, or when a patternbreak is active) */
2948 if (((mp.patpos >= mp.numrow) && (mp.numrow > 0)) && (!mp.posjmp))
2949 mp.posjmp = 3;
2950
2951 if (mp.posjmp)
2952 {
2953 mp.patpos = mp.numrow ? (mp.patbrk % mp.numrow) : 0;
2954 mp.pat_repcrazy = 0;
2955 mp.sngpos += (mp.posjmp - 2);
2956
2957 for (mp.channel = 0; mp.channel < pf->numchn; mp.channel++)
2958 mp.control[mp.channel].pat_reppos = -1;
2959
2960 mp.patbrk = mp.posjmp = 0;
2961 /* handle the "---" (end of song) pattern since it can occur
2962 *inside* the module in .IT and .S3M */
2963 if ((mp.sngpos >= pf->numpos) || (pf->positions[mp.sngpos] == 255))
2964 return 0;
2965
2966 if (mp.sngpos < 0)
2967 mp.sngpos = pf->numpos - 1;
2968
2969 }
2970
2971 if (!mp.patdly2)
2972 pt_Notes ();
2973 }
2974
2975 pt_EffectsPass1 ();
2976 if (pf->flags & UF_NNA)
2977 pt_NNA ();
2978 pt_SetupVoices ();
2979 pt_EffectsPass2 ();
2980
2981 /* now set up the actual hardware channel playback information */
2982 pt_UpdateVoices ();
2983 return 1;
2984 }
2985
2986 BOOL
mod_do_play(MODULE * mf)2987 mod_do_play (MODULE * mf)
2988 {
2989 int t;
2990
2991 /* make sure the player doesn't start with garbage */
2992 memset(&mp, 0, sizeof(mp));
2993 mp.control = (MP_CONTROL *) safe_malloc (mf->numchn * sizeof (MP_CONTROL));
2994 if (!mp.control)
2995 return 1;
2996
2997 memset (mp.control, 0, mf->numchn * sizeof (MP_CONTROL));
2998 for (t = 0; t < mf->numchn; t++)
2999 {
3000 mp.control[t].chanvol = mf->chanvol[t];
3001 mp.control[t].panning = mf->panning[t];
3002 }
3003
3004 mp.pat_repcrazy = 0;
3005 mp.sngpos = 0;
3006 mp.sngspd = mf->initspeed ? (mf->initspeed <= 32 ? mf->initspeed : 32) : 6;
3007 mp.volume = mf->initvolume > 128 ? 128 : mf->initvolume;
3008
3009 mp.oldsngspd = mp.sngspd;
3010 mp.vbtick = mp.sngspd;
3011 mp.patdly = 0;
3012 mp.patdly2 = 0;
3013 mp.bpm = mf->inittempo <= 32 ? 32 : mf->inittempo;
3014 mp.newbpm = mp.bpm;
3015
3016 mp.patpos = 0;
3017 mp.posjmp = 2; /* make sure the player fetches the first note */
3018 mp.numrow = -1;
3019 mp.patbrk = 0;
3020 pf = mf;
3021
3022 Voice_StartPlaying ();
3023 Voice_NewTempo (mp.bpm, mp.sngspd);
3024 do
3025 Voice_TickDone ();
3026 while (HandleTick ());
3027 Voice_TickDone ();
3028 Voice_EndPlaying ();
3029
3030 /* reset all sample pans to center */
3031 /* mod routines have already adjusted the pan events, so we don't want
3032 the regular mixing routines to apply them yet again */
3033 for (t = 0; t < 256; t++)
3034 {
3035 if (special_patch[t])
3036 special_patch[t]->sample->panning = 64;
3037 }
3038
3039 /* Done! */
3040 free (mp.control);
3041 return 0;
3042 }
3043