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 /*==============================================================================
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 const CHAR *STM_Signatures[STM_NTRACKERS] = {
52 const 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 BOOL 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 unsigned noteindexcount=0;
76 int *AllocLinear(void)
78 if(of.numsmp>noteindexcount) {
79 noteindexcount=of.numsmp;
80 noteindex=(int*)MikMod_realloc(noteindex,noteindexcount*sizeof(int));
87 MikMod_free(noteindex);
92 int speed_to_finetune(ULONG speed,int sample)
94 int ctmp=0,tmp,note=1,ft=0;
97 while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))<speed) {
103 if((tmp-speed)<(speed-ctmp))
105 tmp=getfrequency(of.flags,getlinearperiod(note<<1,--ft));
109 ctmp=getfrequency(of.flags,getlinearperiod(note<<1,++ft));
113 noteindex[sample]=note-4*OCTAVE;
117 /*========== Order stuff */
119 /* handles S3M and IT orders */
120 void S3MIT_CreateOrders(BOOL curious)
125 memset(of.positions,0,poslookupcnt*sizeof(UWORD));
126 memset(poslookup,-1,256);
127 for(t=0;t<poslookupcnt;t++) {
128 int order=origpositions[t];
129 if(order==255) order=LAST_PATTERN;
130 of.positions[of.numpos]=order;
131 poslookup[t]=of.numpos; /* bug fix for freaky S3Ms / ITs */
132 if(origpositions[t]<254) of.numpos++;
134 /* end of song special order */
135 if((order==LAST_PATTERN)&&(!(curious--))) break;
139 /*========== Effect stuff */
141 /* handles S3M and IT effects */
142 void S3MIT_ProcessCmd(UBYTE cmd, UBYTE inf, unsigned int flags)
145 /* process S3M / IT specific command structure */
149 case 1: /* Axx set speed to xx */
150 UniEffect(UNI_S3MEFFECTA,inf);
152 case 2: /* Bxx position jump */
153 if (inf<poslookupcnt) {
154 /* switch to curious mode if necessary, for example
155 sympex.it, deep joy.it */
156 if(((SBYTE)poslookup[inf]<0)&&(origpositions[inf]!=255))
157 S3MIT_CreateOrders(1);
159 if(!((SBYTE)poslookup[inf]<0))
160 UniPTEffect(0xb,poslookup[inf]);
163 case 3: /* Cxx patternbreak to row xx */
164 if ((flags & S3MIT_OLDSTYLE) && !(flags & S3MIT_IT))
165 UniPTEffect(0xd,(inf>>4)*10+(inf&0xf));
167 UniPTEffect(0xd,inf);
169 case 4: /* Dxy volumeslide */
170 UniEffect(UNI_S3MEFFECTD,inf);
172 case 5: /* Exy toneslide down */
173 UniEffect(UNI_S3MEFFECTE,inf);
175 case 6: /* Fxy toneslide up */
176 UniEffect(UNI_S3MEFFECTF,inf);
178 case 7: /* Gxx Tone portamento, speed xx */
179 if (flags & S3MIT_OLDSTYLE)
180 UniPTEffect(0x3,inf);
182 UniEffect(UNI_ITEFFECTG,inf);
184 case 8: /* Hxy vibrato */
185 if (flags & S3MIT_OLDSTYLE)
186 UniPTEffect(0x4,inf);
188 UniEffect(UNI_ITEFFECTH,inf);
190 case 9: /* Ixy tremor, ontime x, offtime y */
191 if (flags & S3MIT_OLDSTYLE)
192 UniEffect(UNI_S3MEFFECTI,inf);
194 UniEffect(UNI_ITEFFECTI,inf);
196 case 0xa: /* Jxy arpeggio */
197 UniPTEffect(0x0,inf);
199 case 0xb: /* Kxy Dual command H00 & Dxy */
200 if (flags & S3MIT_OLDSTYLE)
203 UniEffect(UNI_ITEFFECTH,0);
204 UniEffect(UNI_S3MEFFECTD,inf);
206 case 0xc: /* Lxy Dual command G00 & Dxy */
207 if (flags & S3MIT_OLDSTYLE)
210 UniEffect(UNI_ITEFFECTG,0);
211 UniEffect(UNI_S3MEFFECTD,inf);
213 case 0xd: /* Mxx Set Channel Volume */
214 UniEffect(UNI_ITEFFECTM,inf);
216 case 0xe: /* Nxy Slide Channel Volume */
217 UniEffect(UNI_ITEFFECTN,inf);
219 case 0xf: /* Oxx set sampleoffset xx00h */
220 UniPTEffect(0x9,inf);
222 case 0x10: /* Pxy Slide Panning Commands */
223 UniEffect(UNI_ITEFFECTP,inf);
225 case 0x11: /* Qxy Retrig (+volumeslide) */
226 UniWriteByte(UNI_S3MEFFECTQ);
227 if(inf && !lo && !(flags & S3MIT_OLDSTYLE))
232 case 0x12: /* Rxy tremolo speed x, depth y */
233 UniEffect(UNI_S3MEFFECTR,inf);
235 case 0x13: /* Sxx special commands */
237 /* change resonant filter settings if necessary */
238 if((filters)&&((inf&0xf)!=activemacro)) {
240 for(inf=0;inf<0x80;inf++)
241 filtersettings[inf].filter=filtermacros[activemacro];
244 /* Scream Tracker does not have samples larger than
245 64 Kb, thus doesn't need the SAx effect */
246 if ((flags & S3MIT_SCREAM) && ((inf & 0xf0) == 0xa0))
249 UniEffect(UNI_ITEFFECTS0,inf);
252 case 0x14: /* Txx tempo */
254 UniEffect(UNI_S3MEFFECTT,inf);
256 if(!(flags & S3MIT_OLDSTYLE))
258 UniEffect(UNI_ITEFFECTT,inf);
261 case 0x15: /* Uxy Fine Vibrato speed x, depth y */
262 if(flags & S3MIT_OLDSTYLE)
263 UniEffect(UNI_S3MEFFECTU,inf);
265 UniEffect(UNI_ITEFFECTU,inf);
267 case 0x16: /* Vxx Set Global Volume */
268 UniEffect(UNI_XMEFFECTG,inf);
270 case 0x17: /* Wxy Global Volume Slide */
271 UniEffect(UNI_ITEFFECTW,inf);
273 case 0x18: /* Xxx amiga command 8xx */
274 if(flags & S3MIT_OLDSTYLE) {
276 UniEffect(UNI_ITEFFECTS0,0x91); /* surround */
278 UniPTEffect(0x8,(inf==128)?255:(inf<<1));
280 UniPTEffect(0x8,inf);
282 case 0x19: /* Yxy Panbrello speed x, depth y */
283 UniEffect(UNI_ITEFFECTY,inf);
285 case 0x1a: /* Zxx midi/resonant filters */
286 if(filtersettings[inf].filter) {
287 UniWriteByte(UNI_ITEFFECTZ);
288 UniWriteByte(filtersettings[inf].filter);
289 UniWriteByte(filtersettings[inf].inf);
296 /*========== Unitrk stuff */
298 /* Generic effect writing routine */
299 void UniEffect(UWORD eff,UWORD dat)
301 if((!eff)||(eff>=UNI_LAST)) return;
304 if(unioperands[eff]==2)
310 /* Appends UNI_PTEFFECTX opcode to the unitrk stream. */
311 void UniPTEffect(UBYTE eff, UBYTE dat)
315 fprintf(stderr,"UniPTEffect called with incorrect eff value %d\n",eff);
318 if((eff)||(dat)||(of.flags&UF_ARPMEM)) UniEffect(UNI_PTEFFECT0+eff,dat);
321 /* Appends UNI_VOLEFFECT + effect/dat to unistream. */
322 void UniVolEffect(UWORD eff,UBYTE dat)
324 if((eff)||(dat)) { /* don't write empty effect */
325 UniWriteByte(UNI_VOLEFFECTS);
326 UniWriteByte(eff);UniWriteByte(dat);