summaryrefslogtreecommitdiff
path: root/apps/plugins/mikmod/mlutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mikmod/mlutil.c')
-rw-r--r--apps/plugins/mikmod/mlutil.c336
1 files changed, 336 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/mlutil.c b/apps/plugins/mikmod/mlutil.c
new file mode 100644
index 0000000000..6d3a05f45d
--- /dev/null
+++ b/apps/plugins/mikmod/mlutil.c
@@ -0,0 +1,336 @@
1/* MikMod sound library
2 (c) 1998, 1999, 2000, 2001 Miodrag Vallat and others - see file AUTHORS
3 for complete list.
4
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.
9
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.
14
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
18 02111-1307, USA.
19*/
20
21/*==============================================================================
22
23 $Id: mlutil.c,v 1.3 2007/12/06 17:43:10 denis111 Exp $
24
25 Utility functions for the module loader
26
27==============================================================================*/
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#ifdef HAVE_MEMORY_H
34#include <memory.h>
35#endif
36#include <string.h>
37
38#include "mikmod_internals.h"
39
40#ifdef SUNOS
41extern int fprintf(FILE *, const char *, ...);
42#endif
43
44/*========== Shared tracker identifiers */
45
46CHAR *STM_Signatures[STM_NTRACKERS] = {
47 "!Scream!",
48 "BMOD2STM",
49 "WUZAMOD!"
50};
51
52CHAR *STM_Version[STM_NTRACKERS] = {
53 "Screamtracker 2",
54 "Converted by MOD2STM (STM format)",
55 "Wuzamod (STM format)"
56};
57
58/*========== Shared loader variables */
59
60SBYTE remap[UF_MAXCHAN]; /* for removing empty channels */
61UBYTE* poslookup=NULL; /* lookup table for pattern jumps after blank
62 pattern removal */
63UWORD poslookupcnt;
64UWORD* origpositions=NULL;
65
66int filters; /* resonant filters in use */
67UBYTE activemacro; /* active midi macro number for Sxx,xx<80h */
68UBYTE filtermacros[UF_MAXMACRO]; /* midi macro settings */
69FILTER filtersettings[UF_MAXFILTER]; /* computed filter settings */
70
71/*========== Linear periods stuff */
72
73int* noteindex=NULL; /* remap value for linear period modules */
74static int noteindexcount=0;
75
76int *AllocLinear(void)
77{
78 if(of.numsmp>noteindexcount) {
79 noteindexcount=of.numsmp;
80 noteindex=MikMod_realloc(noteindex,noteindexcount*sizeof(int));
81 }
82 return noteindex;
83}
84
85void FreeLinear(void)
86{
87 if(noteindex) {
88 MikMod_free(noteindex);
89 noteindex=NULL;
90 }
91 noteindexcount=0;
92}
93
94int speed_to_finetune(ULONG speed,int sample)
95{
96 int ctmp=0,tmp,note=1,finetune=0;
97
98 speed>>=1;
99 while((tmp=getfrequency(of.flags,getlinearperiod(note<<1,0)))<speed) {
100 ctmp=tmp;
101 note++;
102 }
103
104 if(tmp!=speed) {
105 if((tmp-speed)<(speed-ctmp))
106 while(tmp>speed)
107 tmp=getfrequency(of.flags,getlinearperiod(note<<1,--finetune));
108 else {
109 note--;
110 while(ctmp<speed)
111 ctmp=getfrequency(of.flags,getlinearperiod(note<<1,++finetune));
112 }
113 }
114
115 noteindex[sample]=note-4*OCTAVE;
116 return finetune;
117}
118
119/*========== Order stuff */
120
121/* handles S3M and IT orders */
122void S3MIT_CreateOrders(int curious)
123{
124 int t;
125
126 of.numpos = 0;
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++;
135 else
136 /* end of song special order */
137 if((order==LAST_PATTERN)&&(!(curious--))) break;
138 }
139}
140
141/*========== Effect stuff */
142
143/* handles S3M and IT effects */
144void S3MIT_ProcessCmd(UBYTE cmd,UBYTE inf,unsigned int flags)
145{
146 UBYTE hi,lo;
147
148 lo=inf&0xf;
149 hi=inf>>4;
150
151 /* process S3M / IT specific command structure */
152
153 if(cmd!=255) {
154 switch(cmd) {
155 case 1: /* Axx set speed to xx */
156 UniEffect(UNI_S3MEFFECTA,inf);
157 break;
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);
164
165 if(!((SBYTE)poslookup[inf]<0))
166 UniPTEffect(0xb,poslookup[inf]);
167 }
168 break;
169 case 3: /* Cxx patternbreak to row xx */
170 if ((flags & S3MIT_OLDSTYLE) && !(flags & S3MIT_IT))
171 UniPTEffect(0xd,(inf>>4)*10+(inf&0xf));
172 else
173 UniPTEffect(0xd,inf);
174 break;
175 case 4: /* Dxy volumeslide */
176 UniEffect(UNI_S3MEFFECTD,inf);
177 break;
178 case 5: /* Exy toneslide down */
179 UniEffect(UNI_S3MEFFECTE,inf);
180 break;
181 case 6: /* Fxy toneslide up */
182 UniEffect(UNI_S3MEFFECTF,inf);
183 break;
184 case 7: /* Gxx Tone portamento, speed xx */
185 if (flags & S3MIT_OLDSTYLE)
186 UniPTEffect(0x3,inf);
187 else
188 UniEffect(UNI_ITEFFECTG,inf);
189 break;
190 case 8: /* Hxy vibrato */
191 if (flags & S3MIT_OLDSTYLE)
192 UniPTEffect(0x4,inf);
193 else
194 UniEffect(UNI_ITEFFECTH,inf);
195 break;
196 case 9: /* Ixy tremor, ontime x, offtime y */
197 if (flags & S3MIT_OLDSTYLE)
198 UniEffect(UNI_S3MEFFECTI,inf);
199 else
200 UniEffect(UNI_ITEFFECTI,inf);
201 break;
202 case 0xa: /* Jxy arpeggio */
203 UniPTEffect(0x0,inf);
204 break;
205 case 0xb: /* Kxy Dual command H00 & Dxy */
206 if (flags & S3MIT_OLDSTYLE)
207 UniPTEffect(0x4,0);
208 else
209 UniEffect(UNI_ITEFFECTH,0);
210 UniEffect(UNI_S3MEFFECTD,inf);
211 break;
212 case 0xc: /* Lxy Dual command G00 & Dxy */
213 if (flags & S3MIT_OLDSTYLE)
214 UniPTEffect(0x3,0);
215 else
216 UniEffect(UNI_ITEFFECTG,0);
217 UniEffect(UNI_S3MEFFECTD,inf);
218 break;
219 case 0xd: /* Mxx Set Channel Volume */
220 UniEffect(UNI_ITEFFECTM,inf);
221 break;
222 case 0xe: /* Nxy Slide Channel Volume */
223 UniEffect(UNI_ITEFFECTN,inf);
224 break;
225 case 0xf: /* Oxx set sampleoffset xx00h */
226 UniPTEffect(0x9,inf);
227 break;
228 case 0x10: /* Pxy Slide Panning Commands */
229 UniEffect(UNI_ITEFFECTP,inf);
230 break;
231 case 0x11: /* Qxy Retrig (+volumeslide) */
232 UniWriteByte(UNI_S3MEFFECTQ);
233 if(inf && !lo && !(flags & S3MIT_OLDSTYLE))
234 UniWriteByte(1);
235 else
236 UniWriteByte(inf);
237 break;
238 case 0x12: /* Rxy tremolo speed x, depth y */
239 UniEffect(UNI_S3MEFFECTR,inf);
240 break;
241 case 0x13: /* Sxx special commands */
242 if (inf>=0xf0) {
243 /* change resonant filter settings if necessary */
244 if((filters)&&((inf&0xf)!=activemacro)) {
245 activemacro=inf&0xf;
246 for(inf=0;inf<0x80;inf++)
247 filtersettings[inf].filter=filtermacros[activemacro];
248 }
249 } else {
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))
253 break;
254
255 UniEffect(UNI_ITEFFECTS0,inf);
256 }
257 break;
258 case 0x14: /* Txx tempo */
259 if(inf>=0x20)
260 UniEffect(UNI_S3MEFFECTT,inf);
261 else {
262 if(!(flags & S3MIT_OLDSTYLE))
263 /* IT Tempo slide */
264 UniEffect(UNI_ITEFFECTT,inf);
265 }
266 break;
267 case 0x15: /* Uxy Fine Vibrato speed x, depth y */
268 if(flags & S3MIT_OLDSTYLE)
269 UniEffect(UNI_S3MEFFECTU,inf);
270 else
271 UniEffect(UNI_ITEFFECTU,inf);
272 break;
273 case 0x16: /* Vxx Set Global Volume */
274 UniEffect(UNI_XMEFFECTG,inf);
275 break;
276 case 0x17: /* Wxy Global Volume Slide */
277 UniEffect(UNI_ITEFFECTW,inf);
278 break;
279 case 0x18: /* Xxx amiga command 8xx */
280 if(flags & S3MIT_OLDSTYLE) {
281 if(inf>128)
282 UniEffect(UNI_ITEFFECTS0,0x91); /* surround */
283 else
284 UniPTEffect(0x8,(inf==128)?255:(inf<<1));
285 } else
286 UniPTEffect(0x8,inf);
287 break;
288 case 0x19: /* Yxy Panbrello speed x, depth y */
289 UniEffect(UNI_ITEFFECTY,inf);
290 break;
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);
296 }
297 break;
298 }
299 }
300}
301
302/*========== Unitrk stuff */
303
304/* Generic effect writing routine */
305void UniEffect(UWORD eff,UWORD dat)
306{
307 if((!eff)||(eff>=UNI_LAST)) return;
308
309 UniWriteByte(eff);
310 if(unioperands[eff]==2)
311 UniWriteWord(dat);
312 else
313 UniWriteByte(dat);
314}
315
316/* Appends UNI_PTEFFECTX opcode to the unitrk stream. */
317void UniPTEffect(UBYTE eff, UBYTE dat)
318{
319#ifdef MIKMOD_DEBUG
320 if (eff>=0x10)
321 fprintf(stderr,"UniPTEffect called with incorrect eff value %d\n",eff);
322 else
323#endif
324 if((eff)||(dat)||(of.flags&UF_ARPMEM)) UniEffect(UNI_PTEFFECT0+eff,dat);
325}
326
327/* Appends UNI_VOLEFFECT + effect/dat to unistream. */
328void UniVolEffect(UWORD eff,UBYTE dat)
329{
330 if((eff)||(dat)) { /* don't write empty effect */
331 UniWriteByte(UNI_VOLEFFECTS);
332 UniWriteByte(eff);UniWriteByte(dat);
333 }
334}
335
336/* ex:set ts=4: */