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