diff options
Diffstat (limited to 'apps/plugins/mikmod/mplayer.c')
-rw-r--r-- | apps/plugins/mikmod/mplayer.c | 410 |
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 |
46 | extern int fprintf(FILE *, const char *, ...); | 48 | extern int fprintf(int, const char *, ...); |
47 | extern long int random(void); | 49 | extern long int random(void); |
48 | #endif | 50 | #endif |
49 | 51 | ||
50 | /* The currently playing module */ | 52 | /* The currently playing module */ |
51 | MODULE *pf = NULL; | 53 | MODULE *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 | ||
55 | static UWORD oldperiods[OCTAVE*2]={ | 59 | static 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 | ||
62 | static UBYTE VibratoTable[32]={ | 66 | static 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 | ||
67 | static UBYTE avibtab[128]={ | 71 | static 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) */ |
79 | static ULONG lintab[768]={ | 83 | static 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 |
179 | static UWORD logtab[104]={ | 183 | static 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 | ||
208 | static SBYTE PanbrelloTable[256]={ | 212 | static 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 */ |
228 | static int getrandom(int ceil) | 232 | static 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 | |||
786 | static int DoPTEffect8(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 796 | static 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 | |||
799 | static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 809 | static int DoPTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) |
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 | |||
819 | static int DoPTEffectA(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 829 | static 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 | |||
842 | static int DoPTEffectB(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 852 | static 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 | |||
878 | static int DoPTEffectC(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 896 | static 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 | |||
894 | static int DoPTEffectD(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 912 | static 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 | |||
2168 | static int DoVolEffects(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 2195 | static 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 | |||
2219 | static int DoULTEffect9(UWORD tick, UWORD flags, MP_CONTROL *a, MODULE *mod, SWORD channel) | 2246 | static 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 | |||
2310 | typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD); | 2337 | typedef int (*effect_func) (UWORD, UWORD, MP_CONTROL *, MODULE *, SWORD); |
2311 | 2338 | ||
2312 | static effect_func effects[UNI_LAST] = { | 2339 | static 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 | ||
2377 | static int pt_playeffects(MODULE *mod, SWORD channel, MP_CONTROL *a) | 2404 | static 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) | |||
3166 | MIKMODAPI void Player_SetVolume(SWORD volume) | 3202 | MIKMODAPI 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 | ||
3313 | static void Player_Unmute_internal(SLONG arg1,va_list ap) | 3351 | static 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) | |||
3499 | MIKMODAPI void Player_SetSpeed(UWORD speed) | 3537 | MIKMODAPI 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 | ||
3543 | MIKMODAPI int Player_GetOrder(void) | 3580 | MIKMODAPI 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 */ |
3553 | MIKMODAPI int Player_GetRow(void) | 3590 | MIKMODAPI 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: */ |