summaryrefslogtreecommitdiff
path: root/apps/plugins/mikmod/mplayer.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/mplayer.c')
-rw-r--r--apps/plugins/mikmod/mplayer.c410
1 files changed, 223 insertions, 187 deletions
diff --git a/apps/plugins/mikmod/mplayer.c b/apps/plugins/mikmod/mplayer.c
index 88d6a81af4..ee5c2d187e 100644
--- a/apps/plugins/mikmod/mplayer.c
+++ b/apps/plugins/mikmod/mplayer.c
@@ -6,12 +6,12 @@
6 it under the terms of the GNU Library General Public License as 6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of 7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version. 8 the License, or (at your option) any later version.
9 9
10 This program is distributed in the hope that it will be useful, 10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details. 13 GNU Library General Public License for more details.
14 14
15 You should have received a copy of the GNU Library General Public 15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software 16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -20,7 +20,7 @@
20 20
21/*============================================================================== 21/*==============================================================================
22 22
23 $Id: mplayer.c,v 1.4 2006/08/08 00:06:31 realtech Exp $ 23 $Id$
24 24
25 The Protracker Player Driver 25 The Protracker Player Driver
26 26
@@ -40,31 +40,35 @@
40#include <stdlib.h> 40#include <stdlib.h>
41#endif 41#endif
42 42
43#include <limits.h>
44
43#include "mikmod_internals.h" 45#include "mikmod_internals.h"
44 46
45#ifdef SUNOS 47#ifdef SUNOS
46extern int fprintf(FILE *, const char *, ...); 48extern int fprintf(int, const char *, ...);
47extern long int random(void); 49extern long int random(void);
48#endif 50#endif
49 51
50/* The currently playing module */ 52/* The currently playing module */
51MODULE *pf = NULL; 53MODULE *pf = NULL;
52 54
55#define NUMVOICES(mod) (md_sngchn < (mod)->numvoices ? md_sngchn : (mod)->numvoices)
56
53#define HIGH_OCTAVE 2 /* number of above-range octaves */ 57#define HIGH_OCTAVE 2 /* number of above-range octaves */
54 58
55static UWORD oldperiods[OCTAVE*2]={ 59static const UWORD oldperiods[OCTAVE*2]={
56 0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80, 60 0x6b00, 0x6800, 0x6500, 0x6220, 0x5f50, 0x5c80,
57 0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0, 61 0x5a00, 0x5740, 0x54d0, 0x5260, 0x5010, 0x4dc0,
58 0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160, 62 0x4b90, 0x4960, 0x4750, 0x4540, 0x4350, 0x4160,
59 0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700 63 0x3f90, 0x3dc0, 0x3c10, 0x3a40, 0x38b0, 0x3700
60}; 64};
61 65
62static UBYTE VibratoTable[32]={ 66static const UBYTE VibratoTable[32]={
63 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253, 67 0, 24, 49, 74, 97,120,141,161,180,197,212,224,235,244,250,253,
64 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24 68 255,253,250,244,235,224,212,197,180,161,141,120, 97, 74, 49, 24
65}; 69};
66 70
67static UBYTE avibtab[128]={ 71static const UBYTE avibtab[128]={
68 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23, 72 0, 1, 3, 4, 6, 7, 9,10,12,14,15,17,18,20,21,23,
69 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44, 73 24,25,27,28,30,31,32,34,35,36,38,39,40,41,42,44,
70 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58, 74 45,46,47,48,49,50,51,52,53,54,54,55,56,57,57,58,
@@ -76,7 +80,7 @@ static UBYTE avibtab[128]={
76}; 80};
77 81
78/* Triton's linear periods to frequency translation table (for XM modules) */ 82/* Triton's linear periods to frequency translation table (for XM modules) */
79static ULONG lintab[768]={ 83static const ULONG lintab[768]={
80 535232,534749,534266,533784,533303,532822,532341,531861, 84 535232,534749,534266,533784,533303,532822,532341,531861,
81 531381,530902,530423,529944,529466,528988,528511,528034, 85 531381,530902,530423,529944,529466,528988,528511,528034,
82 527558,527082,526607,526131,525657,525183,524709,524236, 86 527558,527082,526607,526131,525657,525183,524709,524236,
@@ -176,7 +180,7 @@ static ULONG lintab[768]={
176}; 180};
177 181
178#define LOGFAC 2*16 182#define LOGFAC 2*16
179static UWORD logtab[104]={ 183static const UWORD logtab[104]={
180 LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887, 184 LOGFAC*907,LOGFAC*900,LOGFAC*894,LOGFAC*887,
181 LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862, 185 LOGFAC*881,LOGFAC*875,LOGFAC*868,LOGFAC*862,
182 LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838, 186 LOGFAC*856,LOGFAC*850,LOGFAC*844,LOGFAC*838,
@@ -205,7 +209,7 @@ static UWORD logtab[104]={
205 LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431 209 LOGFAC*440,LOGFAC*437,LOGFAC*434,LOGFAC*431
206}; 210};
207 211
208static SBYTE PanbrelloTable[256]={ 212static const SBYTE PanbrelloTable[256]={
209 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23, 213 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23,
210 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44, 214 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44,
211 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 215 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59,
@@ -225,12 +229,12 @@ static SBYTE PanbrelloTable[256]={
225}; 229};
226 230
227/* returns a random value between 0 and ceil-1, ceil must be a power of two */ 231/* returns a random value between 0 and ceil-1, ceil must be a power of two */
228static int getrandom(int ceil) 232static int getrandom(int ceilval)
229{ 233{
230#ifdef HAVE_SRANDOM 234#if defined(HAVE_SRANDOM) && !defined(_MIKMOD_AMIGA)
231 return random()&(ceil-1); 235 return random()&(ceilval-1);
232#else 236#else
233 return (rand()*ceil)/(RAND_MAX+1.0); 237 return (rand()*ceilval)/(RAND_MAX+1.0);
234#endif 238#endif
235} 239}
236 240
@@ -246,14 +250,14 @@ static int MP_FindEmptyChannel(MODULE *mod)
246 MP_VOICE *a; 250 MP_VOICE *a;
247 ULONG t,k,tvol,pp; 251 ULONG t,k,tvol,pp;
248 252
249 for (t=0;t<md_sngchn;t++) 253 for (t=0;t<NUMVOICES(mod);t++)
250 if (((mod->voice[t].main.kick==KICK_ABSENT)|| 254 if (((mod->voice[t].main.kick==KICK_ABSENT)||
251 (mod->voice[t].main.kick==KICK_ENV))&& 255 (mod->voice[t].main.kick==KICK_ENV))&&
252 Voice_Stopped_internal(t)) 256 Voice_Stopped_internal(t))
253 return t; 257 return t;
254 258
255 tvol=0xffffffUL;t=-1;a=mod->voice; 259 tvol=0xffffffUL;t=-1;a=mod->voice;
256 for (k=0;k<md_sngchn;k++,a++) { 260 for (k=0;k<NUMVOICES(mod);k++,a++) {
257 /* allow us to take over a nonexisting sample */ 261 /* allow us to take over a nonexisting sample */
258 if (!a->main.s) 262 if (!a->main.s)
259 return k; 263 return k;
@@ -325,9 +329,9 @@ static UWORD GetPeriod(UWORD flags, UWORD note, ULONG speed)
325{ 329{
326 if (flags & UF_XMPERIODS) { 330 if (flags & UF_XMPERIODS) {
327 if (flags & UF_LINEAR) 331 if (flags & UF_LINEAR)
328 return getlinearperiod(note, speed); 332 return getlinearperiod(note, speed);
329 else 333 else
330 return getlogperiod(note, speed); 334 return getlogperiod(note, speed);
331 } else 335 } else
332 return getoldperiod(note, speed); 336 return getoldperiod(note, speed);
333} 337}
@@ -359,9 +363,15 @@ static SWORD StartEnvelope(ENVPR *t,UBYTE flg,UBYTE pts,UBYTE susbeg,UBYTE susen
359 t->a=0; 363 t->a=0;
360 t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1; 364 t->b=((t->flg&EF_SUSTAIN)&&(!(keyoff&KEY_OFF)))?0:1;
361 365
366 if (!t->pts) { /* FIXME: bad/crafted file. better/more general solution? */
367 t->b=0;
368 return t->env[0].val;
369 }
370
362 /* Imago Orpheus sometimes stores an extra initial point in the envelope */ 371 /* Imago Orpheus sometimes stores an extra initial point in the envelope */
363 if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) { 372 if ((t->pts>=2)&&(t->env[0].pos==t->env[1].pos)) {
364 t->a++;t->b++; 373 t->a++;
374 t->b++;
365 } 375 }
366 376
367 /* Fit in the envelope, still */ 377 /* Fit in the envelope, still */
@@ -615,10 +625,10 @@ static void DoToneSlide(UWORD tick, MP_CONTROL *a)
615 /* ...make tmpperiod equal tperiod */ 625 /* ...make tmpperiod equal tperiod */
616 a->tmpperiod=a->main.period=a->wantedperiod; 626 a->tmpperiod=a->main.period=a->wantedperiod;
617 else if (dist>0) { 627 else if (dist>0) {
618 a->tmpperiod-=a->portspeed; 628 a->tmpperiod-=a->portspeed;
619 a->main.period-=a->portspeed; /* dist>0, slide up */ 629 a->main.period-=a->portspeed; /* dist>0, slide up */
620 } else { 630 } else {
621 a->tmpperiod+=a->portspeed; 631 a->tmpperiod+=a->portspeed;
622 a->main.period+=a->portspeed; /* dist<0, slide down */ 632 a->main.period+=a->portspeed; /* dist<0, slide down */
623 } 633 }
624 } else 634 } else
@@ -786,8 +796,8 @@ static int DoPTEffect7(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
786static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 796static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
787{ 797{
788 UBYTE dat; 798 UBYTE dat;
789 (void)tick; 799 (void)tick;
790 (void)flags; 800 (void)flags;
791 801
792 dat = UniGetByte(); 802 dat = UniGetByte();
793 if (mod->panflag) 803 if (mod->panflag)
@@ -799,16 +809,16 @@ static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
799static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 809static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
800{ 810{
801 UBYTE dat; 811 UBYTE dat;
802 (void)flags; 812 (void)flags;
803 (void)mod; 813 (void)mod;
804 (void)channel; 814 (void)channel;
805 815
806 dat=UniGetByte(); 816 dat=UniGetByte();
807 if (!tick) { 817 if (!tick) {
808 if (dat) a->soffset=(UWORD)dat<<8; 818 if (dat) a->soffset=(UWORD)dat<<8;
809 a->main.start=a->hioffset|a->soffset; 819 a->main.start=a->hioffset|a->soffset;
810 820
811 if ((a->main.s)&&(a->main.start > (SLONG)a->main.s->length)) 821 if ((a->main.s)&&(a->main.start>(SLONG)a->main.s->length))
812 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? 822 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
813 a->main.s->loopstart:a->main.s->length; 823 a->main.s->loopstart:a->main.s->length;
814 } 824 }
@@ -819,9 +829,9 @@ static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
819static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 829static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
820{ 830{
821 UBYTE dat; 831 UBYTE dat;
822 (void)flags; 832 (void)flags;
823 (void)mod; 833 (void)mod;
824 (void)channel; 834 (void)channel;
825 835
826 dat=UniGetByte(); 836 dat=UniGetByte();
827 if (tick) 837 if (tick)
@@ -842,14 +852,19 @@ static int DoPTEffect6(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
842static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 852static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
843{ 853{
844 UBYTE dat; 854 UBYTE dat;
845 (void)a; 855 (void)a;
846 (void)channel; 856 (void)channel;
847 857
848 dat=UniGetByte(); 858 dat=UniGetByte();
849 859
850 if (tick || mod->patdly2) 860 if (tick || mod->patdly2)
851 return 0; 861 return 0;
852 862
863 if (dat >= mod->numpos) { /* crafted file? */
864 /* fprintf(stderr,"DoPTEffectB: numpos=%d, dat=%d -> %d\n",mod->numpos,dat,mod->numpos-1);*/
865 dat=mod->numpos-1;
866 }
867
853 /* Vincent Voois uses a nasty trick in "Universal Bolero" */ 868 /* Vincent Voois uses a nasty trick in "Universal Bolero" */
854 if (dat == mod->sngpos && mod->patbrk == mod->patpos) 869 if (dat == mod->sngpos && mod->patbrk == mod->patpos)
855 return 0; 870 return 0;
@@ -857,8 +872,8 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
857 if (!mod->loop && !mod->patbrk && 872 if (!mod->loop && !mod->patbrk &&
858 (dat < mod->sngpos || 873 (dat < mod->sngpos ||
859 (mod->sngpos == (mod->numpos - 1) && !mod->patbrk) || 874 (mod->sngpos == (mod->numpos - 1) && !mod->patbrk) ||
860 (dat == mod->sngpos && (flags & UF_NOWRAP)) 875 (dat == mod->sngpos && (flags & UF_NOWRAP)) ) )
861 )) { 876 {
862 /* if we don't loop, better not to skip the end of the 877 /* if we don't loop, better not to skip the end of the
863 pattern, after all... so: 878 pattern, after all... so:
864 mod->patbrk=0; */ 879 mod->patbrk=0; */
@@ -870,6 +885,9 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
870 mod->sngpos=dat; 885 mod->sngpos=dat;
871 mod->posjmp=2; 886 mod->posjmp=2;
872 mod->patpos=0; 887 mod->patpos=0;
888 /* cancel the FT2 pattern loop (E60) bug.
889 * also see DoEEffects() below for it. */
890 if (flags & UF_FT2QUIRKS) mod->patbrk=0;
873 } 891 }
874 892
875 return 0; 893 return 0;
@@ -878,15 +896,15 @@ static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
878static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 896static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
879{ 897{
880 UBYTE dat; 898 UBYTE dat;
881 (void)flags; 899 (void)flags;
882 (void)mod; 900 (void)mod;
883 (void)channel; 901 (void)channel;
884 902
885 dat=UniGetByte(); 903 dat=UniGetByte();
886 if (tick) return 0; 904 if (tick) return 0;
887 if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */ 905 if (dat==(UBYTE)-1) a->anote=dat=0; /* note cut */
888 else if (dat>64) dat=64; 906 else if (dat>64) dat=64;
889 a->tmpvolume=dat; 907 a->tmpvolume=dat;
890 908
891 return 0; 909 return 0;
892} 910}
@@ -894,29 +912,33 @@ static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
894static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 912static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
895{ 913{
896 UBYTE dat; 914 UBYTE dat;
897 (void)a; 915 (void)a;
898 (void)channel; 916 (void)channel;
899 917
900 dat=UniGetByte(); 918 dat=UniGetByte();
901 if ((tick)||(mod->patdly2)) return 0; 919 if ((tick)||(mod->patdly2)) return 0;
902 if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&& 920 if (dat && dat >= mod->numrow) { /* crafted file? */
903 (dat>mod->pattrows[mod->positions[mod->sngpos]])) 921 /* fprintf(stderr,"DoPTEffectD: numrow=%d, dat=%d -> 0\n",mod->numrow,dat);*/
904 dat=mod->pattrows[mod->positions[mod->sngpos]]; 922 dat=0;
905 mod->patbrk=dat; 923 }
906 if (!mod->posjmp) { 924 if ((mod->positions[mod->sngpos]!=LAST_PATTERN)&&
907 /* don't ask me to explain this code - it makes 925 (dat>mod->pattrows[mod->positions[mod->sngpos]])) {
908 backwards.s3m and children.xm (heretic's version) play 926 dat=mod->pattrows[mod->positions[mod->sngpos]];
909 correctly, among others. Take that for granted, or write 927 }
910 the page of comments yourself... you might need some 928 mod->patbrk=dat;
911 aspirin - Miod */ 929 if (!mod->posjmp) {
912 if ((mod->sngpos==mod->numpos-1)&&(dat)&&((mod->loop)|| 930 /* don't ask me to explain this code - it makes
913 (mod->positions[mod->sngpos]==(mod->numpat-1) 931 backwards.s3m and children.xm (heretic's version) play
914 && !(flags&UF_NOWRAP)))) { 932 correctly, among others. Take that for granted, or write
915 mod->sngpos=0; 933 the page of comments yourself... you might need some
916 mod->posjmp=2; 934 aspirin - Miod */
917 } else 935 if ((mod->sngpos==mod->numpos-1)&&(dat)&&
918 mod->posjmp=3; 936 ((mod->loop) || (mod->positions[mod->sngpos]==(mod->numpat-1) && !(flags&UF_NOWRAP)))) {
919 } 937 mod->sngpos=0;
938 mod->posjmp=2;
939 } else
940 mod->posjmp=3;
941 }
920 942
921 return 0; 943 return 0;
922} 944}
@@ -982,8 +1004,13 @@ static void DoEEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod,
982 } else 1004 } else
983 mod->patpos=a->pat_reppos; 1005 mod->patpos=a->pat_reppos;
984 } else a->pat_reppos=POS_NONE; 1006 } else a->pat_reppos=POS_NONE;
985 } else 1007 } else {
986 a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */ 1008 a->pat_reppos=mod->patpos-1; /* set reppos - can be (-1) */
1009 /* emulate the FT2 pattern loop (E60) bug:
1010 * http://milkytracker.org/docs/MilkyTracker.html#fxE6x
1011 * roadblas.xm plays correctly with this. */
1012 if (flags & UF_FT2QUIRKS) mod->patbrk=mod->patpos;
1013 }
987 break; 1014 break;
988 case 0x7: /* set tremolo waveform */ 1015 case 0x7: /* set tremolo waveform */
989 a->wavecontrol&=0x0f; 1016 a->wavecontrol&=0x0f;
@@ -1065,7 +1092,7 @@ static int DoPTEffectF(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
1065 if (tick||mod->patdly2) return 0; 1092 if (tick||mod->patdly2) return 0;
1066 if (mod->extspd&&(dat>=mod->bpmlimit)) 1093 if (mod->extspd&&(dat>=mod->bpmlimit))
1067 mod->bpm=dat; 1094 mod->bpm=dat;
1068 else 1095 else
1069 if (dat) { 1096 if (dat) {
1070 mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat; 1097 mod->sngspd=(dat>=mod->bpmlimit)?mod->bpmlimit-1:dat;
1071 mod->vbtick=0; 1098 mod->vbtick=0;
@@ -1465,7 +1492,7 @@ static int DoXMEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
1465 a->s3mvolslide = inf; 1492 a->s3mvolslide = inf;
1466 else 1493 else
1467 inf = a->s3mvolslide; 1494 inf = a->s3mvolslide;
1468 1495
1469 if (tick) { 1496 if (tick) {
1470 lo=inf&0xf; 1497 lo=inf&0xf;
1471 hi=inf>>4; 1498 hi=inf>>4;
@@ -1608,7 +1635,7 @@ static int DoXMEffectL(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
1608 INSTRUMENT *i=a->main.i; 1635 INSTRUMENT *i=a->main.i;
1609 MP_VOICE *aout; 1636 MP_VOICE *aout;
1610 1637
1611 if ((aout=a->slave)) { 1638 if ((aout=a->slave) != NULL) {
1612 if (aout->venv.env) { 1639 if (aout->venv.env) {
1613 points=i->volenv[i->volpts-1].pos; 1640 points=i->volenv[i->volpts-1].pos;
1614 aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos; 1641 aout->venv.p=aout->venv.env[(dat>points)?points:dat].pos;
@@ -1710,7 +1737,7 @@ static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat)
1710 /* if we don't come from another note, ignore the slide and play the note 1737 /* if we don't come from another note, ignore the slide and play the note
1711 as is */ 1738 as is */
1712 if (!a->oldnote || !a->main.period) 1739 if (!a->oldnote || !a->main.period)
1713 return; 1740 return;
1714 1741
1715 if ((!tick)&&(a->newsamp)){ 1742 if ((!tick)&&(a->newsamp)){
1716 a->main.kick=KICK_NOTE; 1743 a->main.kick=KICK_NOTE;
@@ -1725,15 +1752,15 @@ static void DoITToneSlide(UWORD tick, MP_CONTROL *a, UBYTE dat)
1725 difference between those two values */ 1752 difference between those two values */
1726 dist=a->main.period-a->wantedperiod; 1753 dist=a->main.period-a->wantedperiod;
1727 1754
1728 /* if they are equal or if portamentospeed is too big... */ 1755 /* if they are equal or if portamentospeed is too big... */
1729 if ((!dist)||((a->portspeed<<2)>abs(dist))) 1756 if ((!dist)||((a->portspeed<<2)>abs(dist)))
1730 /* ... make tmpperiod equal tperiod */ 1757 /* ... make tmpperiod equal tperiod */
1731 a->tmpperiod=a->main.period=a->wantedperiod; 1758 a->tmpperiod=a->main.period=a->wantedperiod;
1732 else 1759 else
1733 if (dist>0) { 1760 if (dist>0) {
1734 a->tmpperiod-=a->portspeed<<2; 1761 a->tmpperiod-=a->portspeed<<2;
1735 a->main.period-=a->portspeed<<2; /* dist>0 slide up */ 1762 a->main.period-=a->portspeed<<2; /* dist>0 slide up */
1736 } else { 1763 } else {
1737 a->tmpperiod+=a->portspeed<<2; 1764 a->tmpperiod+=a->portspeed<<2;
1738 a->main.period+=a->portspeed<<2; /* dist<0 slide down */ 1765 a->main.period+=a->portspeed<<2; /* dist<0 slide down */
1739 } 1766 }
@@ -1762,7 +1789,7 @@ static void DoITVibrato(UWORD tick, MP_CONTROL *a, UBYTE dat)
1762 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2; 1789 if (dat&0xf0) a->vibspd=(dat&0xf0)>>2;
1763 } 1790 }
1764 if (!a->main.period) 1791 if (!a->main.period)
1765 return; 1792 return;
1766 1793
1767 q=(a->vibpos>>2)&0x1f; 1794 q=(a->vibpos>>2)&0x1f;
1768 1795
@@ -1867,7 +1894,7 @@ static int DoITEffectN(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWOR
1867 lo=inf&0xf; 1894 lo=inf&0xf;
1868 hi=inf>>4; 1895 hi=inf>>4;
1869 1896
1870 if (!hi) 1897 if (!hi)
1871 a->main.chanvol-=lo; 1898 a->main.chanvol-=lo;
1872 else 1899 else
1873 if (!lo) { 1900 if (!lo) {
@@ -2105,13 +2132,13 @@ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO
2105 switch (c) { 2132 switch (c) {
2106 case SS_GLISSANDO: /* S1x set glissando voice */ 2133 case SS_GLISSANDO: /* S1x set glissando voice */
2107 DoEEffects(tick, flags, a, mod, channel, 0x30|inf); 2134 DoEEffects(tick, flags, a, mod, channel, 0x30|inf);
2108 break; 2135 break;
2109 case SS_FINETUNE: /* S2x set finetune */ 2136 case SS_FINETUNE: /* S2x set finetune */
2110 DoEEffects(tick, flags, a, mod, channel, 0x50|inf); 2137 DoEEffects(tick, flags, a, mod, channel, 0x50|inf);
2111 break; 2138 break;
2112 case SS_VIBWAVE: /* S3x set vibrato waveform */ 2139 case SS_VIBWAVE: /* S3x set vibrato waveform */
2113 DoEEffects(tick, flags, a, mod, channel, 0x40|inf); 2140 DoEEffects(tick, flags, a, mod, channel, 0x40|inf);
2114 break; 2141 break;
2115 case SS_TREMWAVE: /* S4x set tremolo waveform */ 2142 case SS_TREMWAVE: /* S4x set tremolo waveform */
2116 DoEEffects(tick, flags, a, mod, channel, 0x70|inf); 2143 DoEEffects(tick, flags, a, mod, channel, 0x70|inf);
2117 break; 2144 break;
@@ -2130,13 +2157,13 @@ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO
2130 case SS_SURROUND: /* S9x set surround sound */ 2157 case SS_SURROUND: /* S9x set surround sound */
2131 if (mod->panflag) 2158 if (mod->panflag)
2132 a->main.panning = mod->panning[channel] = PAN_SURROUND; 2159 a->main.panning = mod->panning[channel] = PAN_SURROUND;
2133 break; 2160 break;
2134 case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */ 2161 case SS_HIOFFSET: /* SAy set high order sample offset yxx00h */
2135 if (!tick) { 2162 if (!tick) {
2136 a->hioffset=inf<<16; 2163 a->hioffset=inf<<16;
2137 a->main.start=a->hioffset|a->soffset; 2164 a->main.start=a->hioffset|a->soffset;
2138 2165
2139 if ((a->main.s)&&(a->main.start > (SLONG)a->main.s->length)) 2166 if ((a->main.s)&&(a->main.start>(SLONG)a->main.s->length))
2140 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? 2167 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2141 a->main.s->loopstart:a->main.s->length; 2168 a->main.s->loopstart:a->main.s->length;
2142 } 2169 }
@@ -2168,10 +2195,10 @@ static int DoITEffectS0(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO
2168static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 2195static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2169{ 2196{
2170 UBYTE c, inf; 2197 UBYTE c, inf;
2171 (void)channel; 2198 (void)channel;
2172 2199
2173 c = UniGetByte(); 2200 c = UniGetByte();
2174 inf = UniGetByte(); 2201 inf = UniGetByte();
2175 2202
2176 if ((!c)&&(!inf)) { 2203 if ((!c)&&(!inf)) {
2177 c=a->voleffect; 2204 c=a->voleffect;
@@ -2219,16 +2246,16 @@ static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWO
2219static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) 2246static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel)
2220{ 2247{
2221 UWORD offset=UniGetWord(); 2248 UWORD offset=UniGetWord();
2222 (void)tick; 2249 (void)tick;
2223 (void)flags; 2250 (void)flags;
2224 (void)mod; 2251 (void)mod;
2225 (void)channel; 2252 (void)channel;
2226 2253
2227 if (offset) 2254 if (offset)
2228 a->ultoffset=offset; 2255 a->ultoffset=offset;
2229 2256
2230 a->main.start=a->ultoffset<<2; 2257 a->main.start=a->ultoffset<<2;
2231 if ((a->main.s)&&(a->main.start > (SLONG)a->main.s->length)) 2258 if ((a->main.s)&&(a->main.start>(SLONG)a->main.s->length))
2232 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)? 2259 a->main.start=a->main.s->flags&(SF_LOOP|SF_BIDI)?
2233 a->main.s->loopstart:a->main.s->length; 2260 a->main.s->loopstart:a->main.s->length;
2234 2261
@@ -2310,68 +2337,68 @@ static int DoNothing(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD
2310typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD); 2337typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD);
2311 2338
2312static effect_func effects[UNI_LAST] = { 2339static effect_func effects[UNI_LAST] = {
2313 DoNothing, /* 0 */ 2340 DoNothing, /* 0 */
2314 DoNothing, /* UNI_NOTE */ 2341 DoNothing, /* UNI_NOTE */
2315 DoNothing, /* UNI_INSTRUMENT */ 2342 DoNothing, /* UNI_INSTRUMENT */
2316 DoPTEffect0, /* UNI_PTEFFECT0 */ 2343 DoPTEffect0, /* UNI_PTEFFECT0 */
2317 DoPTEffect1, /* UNI_PTEFFECT1 */ 2344 DoPTEffect1, /* UNI_PTEFFECT1 */
2318 DoPTEffect2, /* UNI_PTEFFECT2 */ 2345 DoPTEffect2, /* UNI_PTEFFECT2 */
2319 DoPTEffect3, /* UNI_PTEFFECT3 */ 2346 DoPTEffect3, /* UNI_PTEFFECT3 */
2320 DoPTEffect4, /* UNI_PTEFFECT4 */ 2347 DoPTEffect4, /* UNI_PTEFFECT4 */
2321 DoPTEffect5, /* UNI_PTEFFECT5 */ 2348 DoPTEffect5, /* UNI_PTEFFECT5 */
2322 DoPTEffect6, /* UNI_PTEFFECT6 */ 2349 DoPTEffect6, /* UNI_PTEFFECT6 */
2323 DoPTEffect7, /* UNI_PTEFFECT7 */ 2350 DoPTEffect7, /* UNI_PTEFFECT7 */
2324 DoPTEffect8, /* UNI_PTEFFECT8 */ 2351 DoPTEffect8, /* UNI_PTEFFECT8 */
2325 DoPTEffect9, /* UNI_PTEFFECT9 */ 2352 DoPTEffect9, /* UNI_PTEFFECT9 */
2326 DoPTEffectA, /* UNI_PTEFFECTA */ 2353 DoPTEffectA, /* UNI_PTEFFECTA */
2327 DoPTEffectB, /* UNI_PTEFFECTB */ 2354 DoPTEffectB, /* UNI_PTEFFECTB */
2328 DoPTEffectC, /* UNI_PTEFFECTC */ 2355 DoPTEffectC, /* UNI_PTEFFECTC */
2329 DoPTEffectD, /* UNI_PTEFFECTD */ 2356 DoPTEffectD, /* UNI_PTEFFECTD */
2330 DoPTEffectE, /* UNI_PTEFFECTE */ 2357 DoPTEffectE, /* UNI_PTEFFECTE */
2331 DoPTEffectF, /* UNI_PTEFFECTF */ 2358 DoPTEffectF, /* UNI_PTEFFECTF */
2332 DoS3MEffectA, /* UNI_S3MEFFECTA */ 2359 DoS3MEffectA, /* UNI_S3MEFFECTA */
2333 DoS3MEffectD, /* UNI_S3MEFFECTD */ 2360 DoS3MEffectD, /* UNI_S3MEFFECTD */
2334 DoS3MEffectE, /* UNI_S3MEFFECTE */ 2361 DoS3MEffectE, /* UNI_S3MEFFECTE */
2335 DoS3MEffectF, /* UNI_S3MEFFECTF */ 2362 DoS3MEffectF, /* UNI_S3MEFFECTF */
2336 DoS3MEffectI, /* UNI_S3MEFFECTI */ 2363 DoS3MEffectI, /* UNI_S3MEFFECTI */
2337 DoS3MEffectQ, /* UNI_S3MEFFECTQ */ 2364 DoS3MEffectQ, /* UNI_S3MEFFECTQ */
2338 DoS3MEffectR, /* UNI_S3MEFFECTR */ 2365 DoS3MEffectR, /* UNI_S3MEFFECTR */
2339 DoS3MEffectT, /* UNI_S3MEFFECTT */ 2366 DoS3MEffectT, /* UNI_S3MEFFECTT */
2340 DoS3MEffectU, /* UNI_S3MEFFECTU */ 2367 DoS3MEffectU, /* UNI_S3MEFFECTU */
2341 DoKeyOff, /* UNI_KEYOFF */ 2368 DoKeyOff, /* UNI_KEYOFF */
2342 DoKeyFade, /* UNI_KEYFADE */ 2369 DoKeyFade, /* UNI_KEYFADE */
2343 DoVolEffects, /* UNI_VOLEFFECTS */ 2370 DoVolEffects, /* UNI_VOLEFFECTS */
2344 DoPTEffect4, /* UNI_XMEFFECT4 */ 2371 DoPTEffect4, /* UNI_XMEFFECT4 */
2345 DoXMEffect6, /* UNI_XMEFFECT6 */ 2372 DoXMEffect6, /* UNI_XMEFFECT6 */
2346 DoXMEffectA, /* UNI_XMEFFECTA */ 2373 DoXMEffectA, /* UNI_XMEFFECTA */
2347 DoXMEffectE1, /* UNI_XMEFFECTE1 */ 2374 DoXMEffectE1, /* UNI_XMEFFECTE1 */
2348 DoXMEffectE2, /* UNI_XMEFFECTE2 */ 2375 DoXMEffectE2, /* UNI_XMEFFECTE2 */
2349 DoXMEffectEA, /* UNI_XMEFFECTEA */ 2376 DoXMEffectEA, /* UNI_XMEFFECTEA */
2350 DoXMEffectEB, /* UNI_XMEFFECTEB */ 2377 DoXMEffectEB, /* UNI_XMEFFECTEB */
2351 DoXMEffectG, /* UNI_XMEFFECTG */ 2378 DoXMEffectG, /* UNI_XMEFFECTG */
2352 DoXMEffectH, /* UNI_XMEFFECTH */ 2379 DoXMEffectH, /* UNI_XMEFFECTH */
2353 DoXMEffectL, /* UNI_XMEFFECTL */ 2380 DoXMEffectL, /* UNI_XMEFFECTL */
2354 DoXMEffectP, /* UNI_XMEFFECTP */ 2381 DoXMEffectP, /* UNI_XMEFFECTP */
2355 DoXMEffectX1, /* UNI_XMEFFECTX1 */ 2382 DoXMEffectX1, /* UNI_XMEFFECTX1 */
2356 DoXMEffectX2, /* UNI_XMEFFECTX2 */ 2383 DoXMEffectX2, /* UNI_XMEFFECTX2 */
2357 DoITEffectG, /* UNI_ITEFFECTG */ 2384 DoITEffectG, /* UNI_ITEFFECTG */
2358 DoITEffectH, /* UNI_ITEFFECTH */ 2385 DoITEffectH, /* UNI_ITEFFECTH */
2359 DoITEffectI, /* UNI_ITEFFECTI */ 2386 DoITEffectI, /* UNI_ITEFFECTI */
2360 DoITEffectM, /* UNI_ITEFFECTM */ 2387 DoITEffectM, /* UNI_ITEFFECTM */
2361 DoITEffectN, /* UNI_ITEFFECTN */ 2388 DoITEffectN, /* UNI_ITEFFECTN */
2362 DoITEffectP, /* UNI_ITEFFECTP */ 2389 DoITEffectP, /* UNI_ITEFFECTP */
2363 DoITEffectT, /* UNI_ITEFFECTT */ 2390 DoITEffectT, /* UNI_ITEFFECTT */
2364 DoITEffectU, /* UNI_ITEFFECTU */ 2391 DoITEffectU, /* UNI_ITEFFECTU */
2365 DoITEffectW, /* UNI_ITEFFECTW */ 2392 DoITEffectW, /* UNI_ITEFFECTW */
2366 DoITEffectY, /* UNI_ITEFFECTY */ 2393 DoITEffectY, /* UNI_ITEFFECTY */
2367 DoNothing, /* UNI_ITEFFECTZ */ 2394 DoNothing, /* UNI_ITEFFECTZ */
2368 DoITEffectS0, /* UNI_ITEFFECTS0 */ 2395 DoITEffectS0, /* UNI_ITEFFECTS0 */
2369 DoULTEffect9, /* UNI_ULTEFFECT9 */ 2396 DoULTEffect9, /* UNI_ULTEFFECT9 */
2370 DoMEDSpeed, /* UNI_MEDSPEED */ 2397 DoMEDSpeed, /* UNI_MEDSPEED */
2371 DoMEDEffectF1, /* UNI_MEDEFFECTF1 */ 2398 DoMEDEffectF1, /* UNI_MEDEFFECTF1 */
2372 DoMEDEffectF2, /* UNI_MEDEFFECTF2 */ 2399 DoMEDEffectF2, /* UNI_MEDEFFECTF2 */
2373 DoMEDEffectF3, /* UNI_MEDEFFECTF3 */ 2400 DoMEDEffectF3, /* UNI_MEDEFFECTF3 */
2374 DoOktArp, /* UNI_OKTARP */ 2401 DoOktArp, /* UNI_OKTARP */
2375}; 2402};
2376 2403
2377static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a) 2404static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
@@ -2382,10 +2409,14 @@ static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a)
2382 int explicitslides = 0; 2409 int explicitslides = 0;
2383 effect_func f; 2410 effect_func f;
2384 2411
2385 while((c=UniGetByte())) { 2412 while((c=UniGetByte()) != 0) {
2413#if 0 /* this doesn't normally happen unless things go fubar elsewhere */
2414 if (c >= UNI_LAST)
2415 fprintf(stderr,"fubar'ed opcode %u\n",c);
2416#endif
2386 f = effects[c]; 2417 f = effects[c];
2387 if (f != DoNothing) 2418 if (f != DoNothing)
2388 a->sliding = 0; 2419 a->sliding = 0;
2389 explicitslides |= f(tick, flags, a, mod, channel); 2420 explicitslides |= f(tick, flags, a, mod, channel);
2390 } 2421 }
2391 return explicitslides; 2422 return explicitslides;
@@ -2396,17 +2427,17 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2396 int t; 2427 int t;
2397 MP_VOICE *aout; 2428 MP_VOICE *aout;
2398 2429
2399 dat&=0xf; 2430 dat&=0xf;
2400 aout=(a->slave)?a->slave:NULL; 2431 aout=(a->slave)?a->slave:NULL;
2401 2432
2402 switch (dat) { 2433 switch (dat) {
2403 case 0x0: /* past note cut */ 2434 case 0x0: /* past note cut */
2404 for (t=0;t<md_sngchn;t++) 2435 for (t=0;t<NUMVOICES(mod);t++)
2405 if (mod->voice[t].master==a) 2436 if (mod->voice[t].master==a)
2406 mod->voice[t].main.fadevol=0; 2437 mod->voice[t].main.fadevol=0;
2407 break; 2438 break;
2408 case 0x1: /* past note off */ 2439 case 0x1: /* past note off */
2409 for (t=0;t<md_sngchn;t++) 2440 for (t=0;t<NUMVOICES(mod);t++)
2410 if (mod->voice[t].master==a) { 2441 if (mod->voice[t].master==a) {
2411 mod->voice[t].main.keyoff|=KEY_OFF; 2442 mod->voice[t].main.keyoff|=KEY_OFF;
2412 if ((!(mod->voice[t].venv.flg & EF_ON))|| 2443 if ((!(mod->voice[t].venv.flg & EF_ON))||
@@ -2415,7 +2446,7 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2415 } 2446 }
2416 break; 2447 break;
2417 case 0x2: /* past note fade */ 2448 case 0x2: /* past note fade */
2418 for (t=0;t<md_sngchn;t++) 2449 for (t=0;t<NUMVOICES(mod);t++)
2419 if (mod->voice[t].master==a) 2450 if (mod->voice[t].master==a)
2420 mod->voice[t].main.keyoff|=KEY_FADE; 2451 mod->voice[t].main.keyoff|=KEY_FADE;
2421 break; 2452 break;
@@ -2427,7 +2458,7 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2427 break; 2458 break;
2428 case 0x5: /* set NNA note off */ 2459 case 0x5: /* set NNA note off */
2429 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF; 2460 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_OFF;
2430 break; 2461 break;
2431 case 0x6: /* set NNA note fade */ 2462 case 0x6: /* set NNA note fade */
2432 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE; 2463 a->main.nna=(a->main.nna&~NNA_MASK)|NNA_FADE;
2433 break; 2464 break;
@@ -2442,7 +2473,7 @@ static void DoNNAEffects(MODULE *mod, MP_CONTROL *a, UBYTE dat)
2442 case 0x9: /* disable panning envelope */ 2473 case 0x9: /* disable panning envelope */
2443 if (aout) 2474 if (aout)
2444 aout->main.panflg&=~EF_ON; 2475 aout->main.panflg&=~EF_ON;
2445 break; 2476 break;
2446 case 0xa: /* enable panning envelope */ 2477 case 0xa: /* enable panning envelope */
2447 if (aout) 2478 if (aout)
2448 aout->main.panflg|=EF_ON; 2479 aout->main.panflg|=EF_ON;
@@ -2470,7 +2501,7 @@ static void pt_UpdateVoices(MODULE *mod, int max_volume)
2470 SAMPLE *s; 2501 SAMPLE *s;
2471 2502
2472 mod->totalchn=mod->realchn=0; 2503 mod->totalchn=mod->realchn=0;
2473 for (channel=0;channel<md_sngchn;channel++) { 2504 for (channel=0;channel<NUMVOICES(mod);channel++) {
2474 aout=&mod->voice[channel]; 2505 aout=&mod->voice[channel];
2475 i=aout->main.i; 2506 i=aout->main.i;
2476 s=aout->main.s; 2507 s=aout->main.s;
@@ -2484,7 +2515,7 @@ static void pt_UpdateVoices(MODULE *mod, int max_volume)
2484 2515
2485 if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) { 2516 if ((aout->main.kick==KICK_NOTE)||(aout->main.kick==KICK_KEYOFF)) {
2486 Voice_Play_internal(channel,s,(aout->main.start==-1)? 2517 Voice_Play_internal(channel,s,(aout->main.start==-1)?
2487 ((s->flags&SF_UST_LOOP) ? (SLONG)s->loopstart : 0) : aout->main.start); 2518 ((s->flags&SF_UST_LOOP)?(SLONG)s->loopstart:0):aout->main.start);
2488 aout->main.fadevol=32768; 2519 aout->main.fadevol=32768;
2489 aout->aswppos=0; 2520 aout->aswppos=0;
2490 } 2521 }
@@ -2687,7 +2718,7 @@ static void pt_Notes(MODULE *mod)
2687 UniSetRow(a->row); 2718 UniSetRow(a->row);
2688 funky=0; 2719 funky=0;
2689 2720
2690 while((c=UniGetByte())) 2721 while((c=UniGetByte()) != 0)
2691 switch (c) { 2722 switch (c) {
2692 case UNI_NOTE: 2723 case UNI_NOTE:
2693 funky|=1; 2724 funky|=1;
@@ -2720,7 +2751,7 @@ static void pt_Notes(MODULE *mod)
2720 INSTRUMENT *i; 2751 INSTRUMENT *i;
2721 SAMPLE *s; 2752 SAMPLE *s;
2722 2753
2723 if ((i=a->main.i)) { 2754 if ((i=a->main.i) != NULL) {
2724 if (i->samplenumber[a->anote] >= mod->numsmp) continue; 2755 if (i->samplenumber[a->anote] >= mod->numsmp) continue;
2725 s=&mod->samples[i->samplenumber[a->anote]]; 2756 s=&mod->samples[i->samplenumber[a->anote]];
2726 a->main.note=i->samplenote[a->anote]; 2757 a->main.note=i->samplenote[a->anote];
@@ -2809,7 +2840,7 @@ static void pt_EffectsPass1(MODULE *mod)
2809 for (channel=0;channel<mod->numchn;channel++) { 2840 for (channel=0;channel<mod->numchn;channel++) {
2810 a=&mod->control[channel]; 2841 a=&mod->control[channel];
2811 2842
2812 if ((aout=a->slave)) { 2843 if ((aout=a->slave) != NULL) {
2813 a->main.fadevol=aout->main.fadevol; 2844 a->main.fadevol=aout->main.fadevol;
2814 a->main.period=aout->main.period; 2845 a->main.period=aout->main.period;
2815 if (a->main.kick==KICK_KEYOFF) 2846 if (a->main.kick==KICK_KEYOFF)
@@ -2891,7 +2922,7 @@ static void pt_NNA(MODULE *mod)
2891 if (a->dct!=DCT_OFF) { 2922 if (a->dct!=DCT_OFF) {
2892 int t; 2923 int t;
2893 2924
2894 for (t=0;t<md_sngchn;t++) 2925 for (t=0;t<NUMVOICES(mod);t++)
2895 if ((!Voice_Stopped_internal(t))&& 2926 if ((!Voice_Stopped_internal(t))&&
2896 (mod->voice[t].masterchn==channel)&& 2927 (mod->voice[t].masterchn==channel)&&
2897 (a->main.sample==mod->voice[t].main.sample)) { 2928 (a->main.sample==mod->voice[t].main.sample)) {
@@ -2951,11 +2982,11 @@ static void pt_SetupVoices(MODULE *mod)
2951 if ((newchn=MP_FindEmptyChannel(mod))!=-1) 2982 if ((newchn=MP_FindEmptyChannel(mod))!=-1)
2952 a->slave=&mod->voice[a->slavechn=newchn]; 2983 a->slave=&mod->voice[a->slavechn=newchn];
2953 } 2984 }
2954 } else 2985 } else
2955 a->slave=&mod->voice[a->slavechn=channel]; 2986 a->slave=&mod->voice[a->slavechn=channel];
2956 2987
2957 /* assign parts of MP_VOICE only done for a KICK_NOTE */ 2988 /* assign parts of MP_VOICE only done for a KICK_NOTE */
2958 if ((aout=a->slave)) { 2989 if ((aout=a->slave) != NULL) {
2959 if (aout->mflag && aout->master) aout->master->slave=NULL; 2990 if (aout->mflag && aout->master) aout->master->slave=NULL;
2960 aout->master=a; 2991 aout->master=a;
2961 a->slave=aout; 2992 a->slave=aout;
@@ -2984,7 +3015,7 @@ static void pt_EffectsPass2(MODULE *mod)
2984 if (!a->row) continue; 3015 if (!a->row) continue;
2985 UniSetRow(a->row); 3016 UniSetRow(a->row);
2986 3017
2987 while((c=UniGetByte())) 3018 while((c=UniGetByte()) != 0)
2988 if (c==UNI_ITEFFECTS0) { 3019 if (c==UNI_ITEFFECTS0) {
2989 c=UniGetByte(); 3020 c=UniGetByte();
2990 if ((c>>4)==SS_S7EFFECTS) 3021 if ((c>>4)==SS_S7EFFECTS)
@@ -3016,7 +3047,7 @@ void Player_HandleTick(void)
3016 pf->sngremainder%=pf->bpm; 3047 pf->sngremainder%=pf->bpm;
3017 3048
3018 if (++pf->vbtick>=pf->sngspd) { 3049 if (++pf->vbtick>=pf->sngspd) {
3019 if (pf->pat_repcrazy) 3050 if (pf->pat_repcrazy)
3020 pf->pat_repcrazy=0; /* play 2 times row 0 */ 3051 pf->pat_repcrazy=0; /* play 2 times row 0 */
3021 else 3052 else
3022 pf->patpos++; 3053 pf->patpos++;
@@ -3046,6 +3077,9 @@ void Player_HandleTick(void)
3046 pf->control[channel].pat_reppos=-1; 3077 pf->control[channel].pat_reppos=-1;
3047 3078
3048 pf->patbrk=pf->posjmp=0; 3079 pf->patbrk=pf->posjmp=0;
3080
3081 if (pf->sngpos<0) pf->sngpos=(SWORD)(pf->numpos-1);
3082
3049 /* handle the "---" (end of song) pattern since it can occur 3083 /* handle the "---" (end of song) pattern since it can occur
3050 *inside* the module in some formats */ 3084 *inside* the module in some formats */
3051 if ((pf->sngpos>=pf->numpos)|| 3085 if ((pf->sngpos>=pf->numpos)||
@@ -3060,7 +3094,6 @@ void Player_HandleTick(void)
3060 pf->bpm=pf->inittempo<32?32:pf->inittempo; 3094 pf->bpm=pf->inittempo<32?32:pf->inittempo;
3061 } 3095 }
3062 } 3096 }
3063 if (pf->sngpos<0) pf->sngpos=pf->numpos-1;
3064 } 3097 }
3065 3098
3066 if (!pf->patdly2) 3099 if (!pf->patdly2)
@@ -3093,7 +3126,7 @@ static void Player_Init_internal(MODULE* mod)
3093 mod->control[t].main.chanvol=mod->chanvol[t]; 3126 mod->control[t].main.chanvol=mod->chanvol[t];
3094 mod->control[t].main.panning=mod->panning[t]; 3127 mod->control[t].main.panning=mod->panning[t];
3095 } 3128 }
3096 3129
3097 mod->sngtime=0; 3130 mod->sngtime=0;
3098 mod->sngremainder=0; 3131 mod->sngremainder=0;
3099 3132
@@ -3133,6 +3166,11 @@ int Player_Init(MODULE* mod)
3133 if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE)))) 3166 if (!(mod->voice=(MP_VOICE*)MikMod_calloc(md_sngchn,sizeof(MP_VOICE))))
3134 return 1; 3167 return 1;
3135 3168
3169 /* mod->numvoices was used during loading to clamp md_sngchn.
3170 After loading it's used to remember how big mod->voice is.
3171 */
3172 mod->numvoices = md_sngchn;
3173
3136 Player_Init_internal(mod); 3174 Player_Init_internal(mod);
3137 return 0; 3175 return 0;
3138} 3176}
@@ -3148,10 +3186,8 @@ void Player_Exit_internal(MODULE* mod)
3148 pf=NULL; 3186 pf=NULL;
3149 } 3187 }
3150 3188
3151 if (mod->control) 3189 MikMod_free(mod->control);
3152 MikMod_free(mod->control); 3190 MikMod_free(mod->voice);
3153 if (mod->voice)
3154 MikMod_free(mod->voice);
3155 mod->control=NULL; 3191 mod->control=NULL;
3156 mod->voice=NULL; 3192 mod->voice=NULL;
3157} 3193}
@@ -3166,8 +3202,10 @@ void Player_Exit(MODULE* mod)
3166MIKMODAPI void Player_SetVolume(SWORD volume) 3202MIKMODAPI void Player_SetVolume(SWORD volume)
3167{ 3203{
3168 MUTEX_LOCK(vars); 3204 MUTEX_LOCK(vars);
3169 if (pf) 3205 if (pf) {
3170 pf->volume=(volume<0)?0:(volume>128)?128:volume; 3206 pf->volume=(volume<0)?0:(volume>128)?128:volume;
3207 pf->initvolume=pf->volume;
3208 }
3171 MUTEX_UNLOCK(vars); 3209 MUTEX_UNLOCK(vars);
3172} 3210}
3173 3211
@@ -3241,7 +3279,7 @@ MIKMODAPI void Player_NextPosition(void)
3241 pf->patbrk=0; 3279 pf->patbrk=0;
3242 pf->vbtick=pf->sngspd; 3280 pf->vbtick=pf->sngspd;
3243 3281
3244 for (t=0;t<md_sngchn;t++) { 3282 for (t=0;t<NUMVOICES(pf);t++) {
3245 Voice_Stop_internal(t); 3283 Voice_Stop_internal(t);
3246 pf->voice[t].main.i=NULL; 3284 pf->voice[t].main.i=NULL;
3247 pf->voice[t].main.s=NULL; 3285 pf->voice[t].main.s=NULL;
@@ -3266,7 +3304,7 @@ MIKMODAPI void Player_PrevPosition(void)
3266 pf->patbrk=0; 3304 pf->patbrk=0;
3267 pf->vbtick=pf->sngspd; 3305 pf->vbtick=pf->sngspd;
3268 3306
3269 for (t=0;t<md_sngchn;t++) { 3307 for (t=0;t<NUMVOICES(pf);t++) {
3270 Voice_Stop_internal(t); 3308 Voice_Stop_internal(t);
3271 pf->voice[t].main.i=NULL; 3309 pf->voice[t].main.i=NULL;
3272 pf->voice[t].main.s=NULL; 3310 pf->voice[t].main.s=NULL;
@@ -3293,7 +3331,7 @@ MIKMODAPI void Player_SetPosition(UWORD pos)
3293 pf->sngpos=pos; 3331 pf->sngpos=pos;
3294 pf->vbtick=pf->sngspd; 3332 pf->vbtick=pf->sngspd;
3295 3333
3296 for (t=0;t<md_sngchn;t++) { 3334 for (t=0;t<NUMVOICES(pf);t++) {
3297 Voice_Stop_internal(t); 3335 Voice_Stop_internal(t);
3298 pf->voice[t].main.i=NULL; 3336 pf->voice[t].main.i=NULL;
3299 pf->voice[t].main.s=NULL; 3337 pf->voice[t].main.s=NULL;
@@ -3303,12 +3341,12 @@ MIKMODAPI void Player_SetPosition(UWORD pos)
3303 pf->control[t].main.s=NULL; 3341 pf->control[t].main.s=NULL;
3304 } 3342 }
3305 pf->forbid=0; 3343 pf->forbid=0;
3306 3344
3307 if (!pos) 3345 if (!pos)
3308 Player_Init_internal(pf); 3346 Player_Init_internal(pf);
3309 } 3347 }
3310 MUTEX_UNLOCK(vars); 3348 MUTEX_UNLOCK(vars);
3311} 3349}
3312 3350
3313static void Player_Unmute_internal(SLONG arg1,va_list ap) 3351static void Player_Unmute_internal(SLONG arg1,va_list ap)
3314{ 3352{
@@ -3418,7 +3456,7 @@ static void Player_ToggleMute_internal(SLONG arg1,va_list ap)
3418 } 3456 }
3419 break; 3457 break;
3420 default: 3458 default:
3421 if (arg1<pf->numchn) 3459 if (arg1<pf->numchn)
3422 pf->control[arg1].muted=1-pf->control[arg1].muted; 3460 pf->control[arg1].muted=1-pf->control[arg1].muted;
3423 break; 3461 break;
3424 } 3462 }
@@ -3465,7 +3503,7 @@ MIKMODAPI UWORD Player_GetChannelPeriod(UBYTE chan)
3465 UWORD result=0; 3503 UWORD result=0;
3466 3504
3467 MUTEX_LOCK(vars); 3505 MUTEX_LOCK(vars);
3468 if (pf) 3506 if (pf)
3469 result=(chan<pf->numchn)?pf->control[chan].main.period:0; 3507 result=(chan<pf->numchn)?pf->control[chan].main.period:0;
3470 MUTEX_UNLOCK(vars); 3508 MUTEX_UNLOCK(vars);
3471 3509
@@ -3499,7 +3537,7 @@ MIKMODAPI void Player_TogglePause(void)
3499MIKMODAPI void Player_SetSpeed(UWORD speed) 3537MIKMODAPI void Player_SetSpeed(UWORD speed)
3500{ 3538{
3501 MUTEX_LOCK(vars); 3539 MUTEX_LOCK(vars);
3502 if (pf) 3540 if (pf)
3503 pf->sngspd=speed?(speed<32?speed:32):1; 3541 pf->sngspd=speed?(speed<32?speed:32):1;
3504 MUTEX_UNLOCK(vars); 3542 MUTEX_UNLOCK(vars);
3505} 3543}
@@ -3538,18 +3576,17 @@ MIKMODAPI int Player_QueryVoices(UWORD numvoices, VOICEINFO *vinfo)
3538 return numvoices; 3576 return numvoices;
3539} 3577}
3540 3578
3541 3579/* Get current module order */
3542// Get current module order
3543MIKMODAPI int Player_GetOrder(void) 3580MIKMODAPI int Player_GetOrder(void)
3544{ 3581{
3545 int ret; 3582 int ret;
3546 MUTEX_LOCK(vars); 3583 MUTEX_LOCK(vars);
3547 ret = pf ? pf->sngpos :0; // pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0; 3584 ret = pf ? pf->sngpos :0; /* pf->positions[pf->sngpos ? pf->sngpos-1 : 0]: 0; */
3548 MUTEX_UNLOCK(vars); 3585 MUTEX_UNLOCK(vars);
3549 return ret; 3586 return ret;
3550} 3587}
3551 3588
3552// Get current module row 3589/* Get current module row */
3553MIKMODAPI int Player_GetRow(void) 3590MIKMODAPI int Player_GetRow(void)
3554{ 3591{
3555 int ret; 3592 int ret;
@@ -3559,5 +3596,4 @@ MIKMODAPI int Player_GetRow(void)
3559 return ret; 3596 return ret;
3560} 3597}
3561 3598
3562
3563/* ex:set ts=4: */ 3599/* ex:set ts=4: */