1 /* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
5 This library is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of
8 the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
21 /*==============================================================================
23 $Id: mlutil.c,v 1.3 2007/12/06 17:43:10 denis111 Exp $
25 Utility functions for the module loader
27 ==============================================================================*/
38 #include "mikmod_internals.h"
41 extern int fprintf(FILE *, const char *, ...);
44 /*========== Shared tracker identifiers */
46 CHAR
*STM_Signatures
[STM_NTRACKERS
] = {
52 CHAR
*STM_Version
[STM_NTRACKERS
] = {
54 "Converted by MOD2STM (STM format)",
55 "Wuzamod (STM format)"
58 /*========== Shared loader variables */
60 SBYTE remap
[UF_MAXCHAN
]; /* for removing empty channels */
61 UBYTE
* poslookup
=NULL
; /* lookup table for pattern jumps after blank
64 UWORD
* origpositions
=NULL
;
66 int filters
; /* resonant filters in use */
67 UBYTE activemacro
; /* active midi macro number for Sxx,xx<80h */
68 UBYTE filtermacros
[UF_MAXMACRO
]; /* midi macro settings */
69 FILTER filtersettings
[UF_MAXFILTER
]; /* computed filter settings */
71 /*========== Linear periods stuff */
73 int* noteindex
=NULL
; /* remap value for linear period modules */
74 static int noteindexcount
=0;
76 int *AllocLinear(void)
78 if(of
.numsmp
>noteindexcount
) {
79 noteindexcount
=of
.numsmp
;
80 noteindex
=MikMod_realloc(noteindex
,noteindexcount
*sizeof(int));
88 MikMod_free(noteindex
);
94 int speed_to_finetune(ULONG speed
,int sample
)
96 int ctmp
=0,tmp
,note
=1,finetune
=0;
99 while((tmp
=getfrequency(of
.flags
,getlinearperiod(note
<<1,0)))<speed
) {
105 if((tmp
-speed
)<(speed
-ctmp
))
107 tmp
=getfrequency(of
.flags
,getlinearperiod(note
<<1,--finetune
));
111 ctmp
=getfrequency(of
.flags
,getlinearperiod(note
<<1,++finetune
));
115 noteindex
[sample
]=note
-4*OCTAVE
;
119 /*========== Order stuff */
121 /* handles S3M and IT orders */
122 void S3MIT_CreateOrders(int curious
)
127 memset(of
.positions
,0,poslookupcnt
*sizeof(UWORD
));
128 memset(poslookup
,-1,256);
129 for(t
=0;t
<poslookupcnt
;t
++) {
130 int order
=origpositions
[t
];
131 if(order
==255) order
=LAST_PATTERN
;
132 of
.positions
[of
.numpos
]=order
;
133 poslookup
[t
]=of
.numpos
; /* bug fix for freaky S3Ms / ITs */
134 if(origpositions
[t
]<254) of
.numpos
++;
136 /* end of song special order */
137 if((order
==LAST_PATTERN
)&&(!(curious
--))) break;
141 /*========== Effect stuff */
143 /* handles S3M and IT effects */
144 void S3MIT_ProcessCmd(UBYTE cmd
,UBYTE inf
,unsigned int flags
)
151 /* process S3M / IT specific command structure */
155 case 1: /* Axx set speed to xx */
156 UniEffect(UNI_S3MEFFECTA
,inf
);
158 case 2: /* Bxx position jump */
159 if (inf
<poslookupcnt
) {
160 /* switch to curious mode if necessary, for example
161 sympex.it, deep joy.it */
162 if(((SBYTE
)poslookup
[inf
]<0)&&(origpositions
[inf
]!=255))
163 S3MIT_CreateOrders(1);
165 if(!((SBYTE
)poslookup
[inf
]<0))
166 UniPTEffect(0xb,poslookup
[inf
]);
169 case 3: /* Cxx patternbreak to row xx */
170 if ((flags
& S3MIT_OLDSTYLE
) && !(flags
& S3MIT_IT
))
171 UniPTEffect(0xd,(inf
>>4)*10+(inf
&0xf));
173 UniPTEffect(0xd,inf
);
175 case 4: /* Dxy volumeslide */
176 UniEffect(UNI_S3MEFFECTD
,inf
);
178 case 5: /* Exy toneslide down */
179 UniEffect(UNI_S3MEFFECTE
,inf
);
181 case 6: /* Fxy toneslide up */
182 UniEffect(UNI_S3MEFFECTF
,inf
);
184 case 7: /* Gxx Tone portamento, speed xx */
185 if (flags
& S3MIT_OLDSTYLE
)
186 UniPTEffect(0x3,inf
);
188 UniEffect(UNI_ITEFFECTG
,inf
);
190 case 8: /* Hxy vibrato */
191 if (flags
& S3MIT_OLDSTYLE
)
192 UniPTEffect(0x4,inf
);
194 UniEffect(UNI_ITEFFECTH
,inf
);
196 case 9: /* Ixy tremor, ontime x, offtime y */
197 if (flags
& S3MIT_OLDSTYLE
)
198 UniEffect(UNI_S3MEFFECTI
,inf
);
200 UniEffect(UNI_ITEFFECTI
,inf
);
202 case 0xa: /* Jxy arpeggio */
203 UniPTEffect(0x0,inf
);
205 case 0xb: /* Kxy Dual command H00 & Dxy */
206 if (flags
& S3MIT_OLDSTYLE
)
209 UniEffect(UNI_ITEFFECTH
,0);
210 UniEffect(UNI_S3MEFFECTD
,inf
);
212 case 0xc: /* Lxy Dual command G00 & Dxy */
213 if (flags
& S3MIT_OLDSTYLE
)
216 UniEffect(UNI_ITEFFECTG
,0);
217 UniEffect(UNI_S3MEFFECTD
,inf
);
219 case 0xd: /* Mxx Set Channel Volume */
220 UniEffect(UNI_ITEFFECTM
,inf
);
222 case 0xe: /* Nxy Slide Channel Volume */
223 UniEffect(UNI_ITEFFECTN
,inf
);
225 case 0xf: /* Oxx set sampleoffset xx00h */
226 UniPTEffect(0x9,inf
);
228 case 0x10: /* Pxy Slide Panning Commands */
229 UniEffect(UNI_ITEFFECTP
,inf
);
231 case 0x11: /* Qxy Retrig (+volumeslide) */
232 UniWriteByte(UNI_S3MEFFECTQ
);
233 if(inf
&& !lo
&& !(flags
& S3MIT_OLDSTYLE
))
238 case 0x12: /* Rxy tremolo speed x, depth y */
239 UniEffect(UNI_S3MEFFECTR
,inf
);
241 case 0x13: /* Sxx special commands */
243 /* change resonant filter settings if necessary */
244 if((filters
)&&((inf
&0xf)!=activemacro
)) {
246 for(inf
=0;inf
<0x80;inf
++)
247 filtersettings
[inf
].filter
=filtermacros
[activemacro
];
250 /* Scream Tracker does not have samples larger than
251 64 Kb, thus doesn't need the SAx effect */
252 if ((flags
& S3MIT_SCREAM
) && ((inf
& 0xf0) == 0xa0))
255 UniEffect(UNI_ITEFFECTS0
,inf
);
258 case 0x14: /* Txx tempo */
260 UniEffect(UNI_S3MEFFECTT
,inf
);
262 if(!(flags
& S3MIT_OLDSTYLE
))
264 UniEffect(UNI_ITEFFECTT
,inf
);
267 case 0x15: /* Uxy Fine Vibrato speed x, depth y */
268 if(flags
& S3MIT_OLDSTYLE
)
269 UniEffect(UNI_S3MEFFECTU
,inf
);
271 UniEffect(UNI_ITEFFECTU
,inf
);
273 case 0x16: /* Vxx Set Global Volume */
274 UniEffect(UNI_XMEFFECTG
,inf
);
276 case 0x17: /* Wxy Global Volume Slide */
277 UniEffect(UNI_ITEFFECTW
,inf
);
279 case 0x18: /* Xxx amiga command 8xx */
280 if(flags
& S3MIT_OLDSTYLE
) {
282 UniEffect(UNI_ITEFFECTS0
,0x91); /* surround */
284 UniPTEffect(0x8,(inf
==128)?255:(inf
<<1));
286 UniPTEffect(0x8,inf
);
288 case 0x19: /* Yxy Panbrello speed x, depth y */
289 UniEffect(UNI_ITEFFECTY
,inf
);
291 case 0x1a: /* Zxx midi/resonant filters */
292 if(filtersettings
[inf
].filter
) {
293 UniWriteByte(UNI_ITEFFECTZ
);
294 UniWriteByte(filtersettings
[inf
].filter
);
295 UniWriteByte(filtersettings
[inf
].inf
);
302 /*========== Unitrk stuff */
304 /* Generic effect writing routine */
305 void UniEffect(UWORD eff
,UWORD dat
)
307 if((!eff
)||(eff
>=UNI_LAST
)) return;
310 if(unioperands
[eff
]==2)
316 /* Appends UNI_PTEFFECTX opcode to the unitrk stream. */
317 void UniPTEffect(UBYTE eff
, UBYTE dat
)
321 fprintf(stderr
,"UniPTEffect called with incorrect eff value %d\n",eff
);
324 if((eff
)||(dat
)||(of
.flags
&UF_ARPMEM
)) UniEffect(UNI_PTEFFECT0
+eff
,dat
);
327 /* Appends UNI_VOLEFFECT + effect/dat to unistream. */
328 void UniVolEffect(UWORD eff
,UBYTE dat
)
330 if((eff
)||(dat
)) { /* don't write empty effect */
331 UniWriteByte(UNI_VOLEFFECTS
);
332 UniWriteByte(eff
);UniWriteByte(dat
);