diff options
author | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
---|---|---|
committer | Frank Gevaerts <frank@gevaerts.be> | 2010-12-12 15:03:30 +0000 |
commit | 26f2bfde03420edad4de1f22cb3d515dc063b20d (patch) | |
tree | 4a8c4abaf4795f38da70a4657c1a0fb3ba9debeb /apps/plugins/mikmod/load_imf.c | |
parent | d192bdf11e06e50645ecb5726658d4b691480a9a (diff) | |
download | rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.tar.gz rockbox-26f2bfde03420edad4de1f22cb3d515dc063b20d.zip |
Add MikMod plugin, ported by Jason Yu, with some minor work by Craig Mann and William Peters (FS#8806)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@28810 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mikmod/load_imf.c')
-rw-r--r-- | apps/plugins/mikmod/load_imf.c | 738 |
1 files changed, 738 insertions, 0 deletions
diff --git a/apps/plugins/mikmod/load_imf.c b/apps/plugins/mikmod/load_imf.c new file mode 100644 index 0000000000..0b85c0ecc3 --- /dev/null +++ b/apps/plugins/mikmod/load_imf.c | |||
@@ -0,0 +1,738 @@ | |||
1 | /* MikMod sound library | ||
2 | (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file | ||
3 | AUTHORS 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: load_imf.c,v 1.3 2005/04/07 19:57:38 realtech Exp $ | ||
24 | |||
25 | Imago Orpheus (IMF) module loader | ||
26 | |||
27 | ==============================================================================*/ | ||
28 | |||
29 | #ifdef HAVE_CONFIG_H | ||
30 | #include "config.h" | ||
31 | #endif | ||
32 | |||
33 | #ifdef HAVE_UNISTD_H | ||
34 | #include <unistd.h> | ||
35 | #endif | ||
36 | |||
37 | #include <stdio.h> | ||
38 | #ifdef HAVE_MEMORY_H | ||
39 | #include <memory.h> | ||
40 | #endif | ||
41 | #include <string.h> | ||
42 | |||
43 | #include "mikmod_internals.h" | ||
44 | |||
45 | #ifdef SUNOS | ||
46 | extern int fprintf(FILE *, const char *, ...); | ||
47 | #endif | ||
48 | |||
49 | /*========== Module structure */ | ||
50 | |||
51 | /* module header */ | ||
52 | typedef struct IMFHEADER { | ||
53 | CHAR songname[32]; | ||
54 | UWORD ordnum; | ||
55 | UWORD patnum; | ||
56 | UWORD insnum; | ||
57 | UWORD flags; | ||
58 | UBYTE initspeed; | ||
59 | UBYTE inittempo; | ||
60 | UBYTE mastervol; | ||
61 | UBYTE mastermult; | ||
62 | UBYTE orders[256]; | ||
63 | } IMFHEADER; | ||
64 | |||
65 | /* channel settings */ | ||
66 | typedef struct IMFCHANNEL { | ||
67 | CHAR name[12]; | ||
68 | UBYTE chorus; | ||
69 | UBYTE reverb; | ||
70 | UBYTE pan; | ||
71 | UBYTE status; | ||
72 | } IMFCHANNEL; | ||
73 | |||
74 | /* instrument header */ | ||
75 | #define IMFNOTECNT (10*OCTAVE) | ||
76 | #define IMFENVCNT (16*2) | ||
77 | typedef struct IMFINSTHEADER { | ||
78 | CHAR name[32]; | ||
79 | UBYTE what[IMFNOTECNT]; | ||
80 | UWORD volenv[IMFENVCNT]; | ||
81 | UWORD panenv[IMFENVCNT]; | ||
82 | UWORD pitenv[IMFENVCNT]; | ||
83 | UBYTE volpts; | ||
84 | UBYTE volsus; | ||
85 | UBYTE volbeg; | ||
86 | UBYTE volend; | ||
87 | UBYTE volflg; | ||
88 | UBYTE panpts; | ||
89 | UBYTE pansus; | ||
90 | UBYTE panbeg; | ||
91 | UBYTE panend; | ||
92 | UBYTE panflg; | ||
93 | UBYTE pitpts; | ||
94 | UBYTE pitsus; | ||
95 | UBYTE pitbeg; | ||
96 | UBYTE pitend; | ||
97 | UBYTE pitflg; | ||
98 | UWORD volfade; | ||
99 | UWORD numsmp; | ||
100 | ULONG signature; | ||
101 | } IMFINSTHEADER; | ||
102 | |||
103 | /* sample header */ | ||
104 | typedef struct IMFWAVHEADER { | ||
105 | CHAR samplename[13]; | ||
106 | ULONG length; | ||
107 | ULONG loopstart; | ||
108 | ULONG loopend; | ||
109 | ULONG samplerate; | ||
110 | UBYTE volume; | ||
111 | UBYTE pan; | ||
112 | UBYTE flags; | ||
113 | } IMFWAVHEADER; | ||
114 | |||
115 | typedef struct IMFNOTE { | ||
116 | UBYTE note,ins,eff1,dat1,eff2,dat2; | ||
117 | } IMFNOTE; | ||
118 | |||
119 | /*========== Loader variables */ | ||
120 | |||
121 | static CHAR IMF_Version[]="Imago Orpheus"; | ||
122 | |||
123 | static IMFNOTE *imfpat=NULL; | ||
124 | static IMFHEADER *mh=NULL; | ||
125 | |||
126 | /*========== Loader code */ | ||
127 | |||
128 | int IMF_Test(void) | ||
129 | { | ||
130 | UBYTE id[4]; | ||
131 | |||
132 | _mm_fseek(modreader,0x3c,SEEK_SET); | ||
133 | if(!_mm_read_UBYTES(id,4,modreader)) return 0; | ||
134 | if(!memcmp(id,"IM10",4)) return 1; | ||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | int IMF_Init(void) | ||
139 | { | ||
140 | if(!(imfpat=(IMFNOTE*)MikMod_malloc(32*256*sizeof(IMFNOTE)))) return 0; | ||
141 | if(!(mh=(IMFHEADER*)MikMod_malloc(sizeof(IMFHEADER)))) return 0; | ||
142 | |||
143 | return 1; | ||
144 | } | ||
145 | |||
146 | void IMF_Cleanup(void) | ||
147 | { | ||
148 | FreeLinear(); | ||
149 | |||
150 | MikMod_free(imfpat); | ||
151 | MikMod_free(mh); | ||
152 | } | ||
153 | |||
154 | static int IMF_ReadPattern(SLONG size,UWORD rows) | ||
155 | { | ||
156 | int row=0,flag,ch; | ||
157 | IMFNOTE *n,dummy; | ||
158 | |||
159 | /* clear pattern data */ | ||
160 | memset(imfpat,255,32*256*sizeof(IMFNOTE)); | ||
161 | |||
162 | while((size>0)&&(row<rows)) { | ||
163 | flag=_mm_read_UBYTE(modreader);size--; | ||
164 | |||
165 | if(_mm_eof(modreader)) { | ||
166 | _mm_errno=MMERR_LOADING_PATTERN; | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | if(flag) { | ||
171 | ch=remap[flag&31]; | ||
172 | |||
173 | if(ch!=-1) | ||
174 | n=&imfpat[256*ch+row]; | ||
175 | else | ||
176 | n=&dummy; | ||
177 | |||
178 | if(flag&32) { | ||
179 | n->note=_mm_read_UBYTE(modreader); | ||
180 | if(n->note>=0xa0) n->note=0xa0; /* note off */ | ||
181 | n->ins =_mm_read_UBYTE(modreader); | ||
182 | size-=2; | ||
183 | } | ||
184 | if(flag&64) { | ||
185 | size-=2; | ||
186 | n->eff2=_mm_read_UBYTE(modreader); | ||
187 | n->dat2=_mm_read_UBYTE(modreader); | ||
188 | } | ||
189 | if(flag&128) { | ||
190 | n->eff1=_mm_read_UBYTE(modreader); | ||
191 | n->dat1=_mm_read_UBYTE(modreader); | ||
192 | size-=2; | ||
193 | } | ||
194 | } else row++; | ||
195 | } | ||
196 | if((size)||(row!=rows)) { | ||
197 | _mm_errno=MMERR_LOADING_PATTERN; | ||
198 | return 0; | ||
199 | } | ||
200 | return 1; | ||
201 | } | ||
202 | |||
203 | static void IMF_ProcessCmd(UBYTE eff,UBYTE inf) | ||
204 | { | ||
205 | if((eff)&&(eff!=255)) | ||
206 | switch (eff) { | ||
207 | case 0x01: /* set tempo */ | ||
208 | UniEffect(UNI_S3MEFFECTA,inf); | ||
209 | break; | ||
210 | case 0x02: /* set BPM */ | ||
211 | if(inf>=0x20) UniEffect(UNI_S3MEFFECTT,inf); | ||
212 | break; | ||
213 | case 0x03: /* tone portamento */ | ||
214 | UniEffect(UNI_ITEFFECTG,inf); | ||
215 | break; | ||
216 | case 0x04: /* porta + volslide */ | ||
217 | UniEffect(UNI_ITEFFECTG,inf); | ||
218 | UniEffect(UNI_S3MEFFECTD,0); | ||
219 | break; | ||
220 | case 0x05: /* vibrato */ | ||
221 | UniEffect(UNI_XMEFFECT4,inf); | ||
222 | break; | ||
223 | case 0x06: /* vibrato + volslide */ | ||
224 | UniEffect(UNI_XMEFFECT6,inf); | ||
225 | break; | ||
226 | case 0x07: /* fine vibrato */ | ||
227 | UniEffect(UNI_ITEFFECTU,inf); | ||
228 | break; | ||
229 | case 0x08: /* tremolo */ | ||
230 | UniEffect(UNI_S3MEFFECTR,inf); | ||
231 | break; | ||
232 | case 0x09: /* arpeggio */ | ||
233 | UniPTEffect(0x0,inf); | ||
234 | break; | ||
235 | case 0x0a: /* panning */ | ||
236 | UniPTEffect(0x8,(inf>=128)?255:(inf<<1)); | ||
237 | break; | ||
238 | case 0x0b: /* pan slide */ | ||
239 | UniEffect(UNI_XMEFFECTP,inf); | ||
240 | break; | ||
241 | case 0x0c: /* set channel volume */ | ||
242 | if(inf<=64) UniPTEffect(0xc,inf); | ||
243 | break; | ||
244 | case 0x0d: /* volume slide */ | ||
245 | UniEffect(UNI_S3MEFFECTD,inf); | ||
246 | break; | ||
247 | case 0x0e: /* fine volume slide */ | ||
248 | if(inf) { | ||
249 | if(inf>>4) | ||
250 | UniEffect(UNI_S3MEFFECTD,0x0f|inf); | ||
251 | else | ||
252 | UniEffect(UNI_S3MEFFECTD,0xf0|inf); | ||
253 | } else | ||
254 | UniEffect(UNI_S3MEFFECTD,0); | ||
255 | break; | ||
256 | case 0x0f: /* set finetune */ | ||
257 | UniPTEffect(0xe,0x50|(inf>>4)); | ||
258 | break; | ||
259 | #ifdef MIKMOD_DEBUG | ||
260 | case 0x10: /* note slide up */ | ||
261 | case 0x11: /* not slide down */ | ||
262 | fprintf(stderr,"\rIMF effect 0x10/0x11 (note slide)" | ||
263 | " not implemented (eff=%2X inf=%2X)\n",eff,inf); | ||
264 | break; | ||
265 | #endif | ||
266 | case 0x12: /* slide up */ | ||
267 | UniEffect(UNI_S3MEFFECTF,inf); | ||
268 | break; | ||
269 | case 0x13: /* slide down */ | ||
270 | UniEffect(UNI_S3MEFFECTE,inf); | ||
271 | break; | ||
272 | case 0x14: /* fine slide up */ | ||
273 | if (inf) { | ||
274 | if (inf<0x40) | ||
275 | UniEffect(UNI_S3MEFFECTF,0xe0|(inf>>2)); | ||
276 | else | ||
277 | UniEffect(UNI_S3MEFFECTF,0xf0|(inf>>4)); | ||
278 | } else | ||
279 | UniEffect(UNI_S3MEFFECTF,0); | ||
280 | break; | ||
281 | case 0x15: /* fine slide down */ | ||
282 | if (inf) { | ||
283 | if (inf<0x40) | ||
284 | UniEffect(UNI_S3MEFFECTE,0xe0|(inf>>2)); | ||
285 | else | ||
286 | UniEffect(UNI_S3MEFFECTE,0xf0|(inf>>4)); | ||
287 | } else | ||
288 | UniEffect(UNI_S3MEFFECTE,0); | ||
289 | break; | ||
290 | /* 0x16 set filter cutoff (awe32) */ | ||
291 | /* 0x17 filter side + resonance (awe32) */ | ||
292 | case 0x18: /* sample offset */ | ||
293 | UniPTEffect(0x9,inf); | ||
294 | break; | ||
295 | #ifdef MIKMOD_DEBUG | ||
296 | case 0x19: /* set fine sample offset */ | ||
297 | fprintf(stderr,"\rIMF effect 0x19 (fine sample offset)" | ||
298 | " not implemented (inf=%2X)\n",inf); | ||
299 | break; | ||
300 | #endif | ||
301 | case 0x1a: /* keyoff */ | ||
302 | UniWriteByte(UNI_KEYOFF); | ||
303 | break; | ||
304 | case 0x1b: /* retrig */ | ||
305 | UniEffect(UNI_S3MEFFECTQ,inf); | ||
306 | break; | ||
307 | case 0x1c: /* tremor */ | ||
308 | UniEffect(UNI_S3MEFFECTI,inf); | ||
309 | break; | ||
310 | case 0x1d: /* position jump */ | ||
311 | UniPTEffect(0xb,inf); | ||
312 | break; | ||
313 | case 0x1e: /* pattern break */ | ||
314 | UniPTEffect(0xd,(inf>>4)*10+(inf&0xf)); | ||
315 | break; | ||
316 | case 0x1f: /* set master volume */ | ||
317 | if(inf<=64) UniEffect(UNI_XMEFFECTG,inf<<1); | ||
318 | break; | ||
319 | case 0x20: /* master volume slide */ | ||
320 | UniEffect(UNI_XMEFFECTH,inf); | ||
321 | break; | ||
322 | case 0x21: /* extended effects */ | ||
323 | switch(inf>>4) { | ||
324 | case 0x1: /* set filter */ | ||
325 | case 0x5: /* vibrato waveform */ | ||
326 | case 0x8: /* tremolo waveform */ | ||
327 | UniPTEffect(0xe,inf-0x10); | ||
328 | break; | ||
329 | case 0xa: /* pattern loop */ | ||
330 | UniPTEffect(0xe,0x60|(inf&0xf)); | ||
331 | break; | ||
332 | case 0xb: /* pattern delay */ | ||
333 | UniPTEffect(0xe,0xe0|(inf&0xf)); | ||
334 | break; | ||
335 | case 0x3: /* glissando */ | ||
336 | case 0xc: /* note cut */ | ||
337 | case 0xd: /* note delay */ | ||
338 | case 0xf: /* invert loop */ | ||
339 | UniPTEffect(0xe,inf); | ||
340 | break; | ||
341 | case 0xe: /* ignore envelope */ | ||
342 | UniEffect(UNI_ITEFFECTS0, 0x77); /* vol */ | ||
343 | UniEffect(UNI_ITEFFECTS0, 0x79); /* pan */ | ||
344 | UniEffect(UNI_ITEFFECTS0, 0x7b); /* pit */ | ||
345 | break; | ||
346 | } | ||
347 | break; | ||
348 | /* 0x22 chorus (awe32) */ | ||
349 | /* 0x23 reverb (awe32) */ | ||
350 | } | ||
351 | } | ||
352 | |||
353 | static UBYTE* IMF_ConvertTrack(IMFNOTE* tr,UWORD rows) | ||
354 | { | ||
355 | int t; | ||
356 | UBYTE note,ins; | ||
357 | |||
358 | UniReset(); | ||
359 | for(t=0;t<rows;t++) { | ||
360 | note=tr[t].note; | ||
361 | ins=tr[t].ins; | ||
362 | |||
363 | if((ins)&&(ins!=255)) UniInstrument(ins-1); | ||
364 | if(note!=255) { | ||
365 | if(note==0xa0) { | ||
366 | UniPTEffect(0xc,0); /* Note cut */ | ||
367 | if(tr[t].eff1==0x0c) tr[t].eff1=0; | ||
368 | if(tr[t].eff2==0x0c) tr[t].eff2=0; | ||
369 | } else | ||
370 | UniNote(((note>>4)*OCTAVE)+(note&0xf)); | ||
371 | } | ||
372 | |||
373 | IMF_ProcessCmd(tr[t].eff1,tr[t].dat1); | ||
374 | IMF_ProcessCmd(tr[t].eff2,tr[t].dat2); | ||
375 | UniNewline(); | ||
376 | } | ||
377 | return UniDup(); | ||
378 | } | ||
379 | |||
380 | int IMF_Load(int curious) | ||
381 | { | ||
382 | #define IMF_SMPINCR 64 | ||
383 | int t,u,track=0,oldnumsmp; | ||
384 | IMFCHANNEL channels[32]; | ||
385 | INSTRUMENT *d; | ||
386 | SAMPLE *q; | ||
387 | IMFWAVHEADER *wh=NULL,*s=NULL; | ||
388 | ULONG *nextwav=NULL; | ||
389 | UWORD wavcnt=0; | ||
390 | UBYTE id[4]; | ||
391 | |||
392 | /* try to read the module header */ | ||
393 | _mm_read_string(mh->songname,32,modreader); | ||
394 | mh->ordnum=_mm_read_I_UWORD(modreader); | ||
395 | mh->patnum=_mm_read_I_UWORD(modreader); | ||
396 | mh->insnum=_mm_read_I_UWORD(modreader); | ||
397 | mh->flags =_mm_read_I_UWORD(modreader); | ||
398 | _mm_fseek(modreader,8,SEEK_CUR); | ||
399 | mh->initspeed =_mm_read_UBYTE(modreader); | ||
400 | mh->inittempo =_mm_read_UBYTE(modreader); | ||
401 | mh->mastervol =_mm_read_UBYTE(modreader); | ||
402 | mh->mastermult=_mm_read_UBYTE(modreader); | ||
403 | _mm_fseek(modreader,64,SEEK_SET); | ||
404 | |||
405 | if(_mm_eof(modreader)) { | ||
406 | _mm_errno = MMERR_LOADING_HEADER; | ||
407 | return 0; | ||
408 | } | ||
409 | |||
410 | /* set module variables */ | ||
411 | of.songname=DupStr(mh->songname,31,1); | ||
412 | of.modtype=StrDup(IMF_Version); | ||
413 | of.numpat=mh->patnum; | ||
414 | of.numins=mh->insnum; | ||
415 | of.reppos=0; | ||
416 | of.initspeed=mh->initspeed; | ||
417 | of.inittempo=mh->inittempo; | ||
418 | of.initvolume=mh->mastervol<<1; | ||
419 | of.flags |= UF_INST | UF_ARPMEM | UF_PANNING; | ||
420 | if(mh->flags&1) of.flags |= UF_LINEAR; | ||
421 | of.bpmlimit=32; | ||
422 | |||
423 | /* read channel information */ | ||
424 | of.numchn=0; | ||
425 | memset(remap,-1,32*sizeof(UBYTE)); | ||
426 | for(t=0;t<32;t++) { | ||
427 | _mm_read_string(channels[t].name,12,modreader); | ||
428 | channels[t].chorus=_mm_read_UBYTE(modreader); | ||
429 | channels[t].reverb=_mm_read_UBYTE(modreader); | ||
430 | channels[t].pan =_mm_read_UBYTE(modreader); | ||
431 | channels[t].status=_mm_read_UBYTE(modreader); | ||
432 | } | ||
433 | /* bug in Imago Orpheus ? If only channel 1 is enabled, in fact we have to | ||
434 | enable 16 channels */ | ||
435 | if(!channels[0].status) { | ||
436 | for(t=1;t<16;t++) if(channels[t].status!=1) break; | ||
437 | if(t==16) for(t=1;t<16;t++) channels[t].status=0; | ||
438 | } | ||
439 | for(t=0;t<32;t++) { | ||
440 | if(channels[t].status!=2) | ||
441 | remap[t]=of.numchn++; | ||
442 | else | ||
443 | remap[t]=-1; | ||
444 | } | ||
445 | for(t=0;t<32;t++) | ||
446 | if(remap[t]!=-1) { | ||
447 | of.panning[remap[t]]=channels[t].pan; | ||
448 | of.chanvol[remap[t]]=channels[t].status?0:64; | ||
449 | } | ||
450 | |||
451 | if(_mm_eof(modreader)) { | ||
452 | _mm_errno = MMERR_LOADING_HEADER; | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | /* read order list */ | ||
457 | _mm_read_UBYTES(mh->orders,256,modreader); | ||
458 | if(_mm_eof(modreader)) { | ||
459 | _mm_errno = MMERR_LOADING_HEADER; | ||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | of.numpos=0; | ||
464 | for(t=0;t<mh->ordnum;t++) | ||
465 | if(mh->orders[t]!=0xff) of.numpos++; | ||
466 | if(!AllocPositions(of.numpos)) return 0; | ||
467 | for(t=u=0;t<mh->ordnum;t++) | ||
468 | if(mh->orders[t]!=0xff) of.positions[u++]=mh->orders[t]; | ||
469 | |||
470 | /* load pattern info */ | ||
471 | of.numtrk=of.numpat*of.numchn; | ||
472 | if(!AllocTracks()) return 0; | ||
473 | if(!AllocPatterns()) return 0; | ||
474 | |||
475 | for(t=0;t<of.numpat;t++) { | ||
476 | SLONG size; | ||
477 | UWORD rows; | ||
478 | |||
479 | size=(SLONG)_mm_read_I_UWORD(modreader); | ||
480 | rows=_mm_read_I_UWORD(modreader); | ||
481 | if((rows>256)||(size<4)) { | ||
482 | _mm_errno=MMERR_LOADING_PATTERN; | ||
483 | return 0; | ||
484 | } | ||
485 | |||
486 | of.pattrows[t]=rows; | ||
487 | if(!IMF_ReadPattern(size-4,rows)) return 0; | ||
488 | for(u=0;u<of.numchn;u++) | ||
489 | if(!(of.tracks[track++]=IMF_ConvertTrack(&imfpat[u*256],rows))) | ||
490 | return 0; | ||
491 | } | ||
492 | |||
493 | /* load instruments */ | ||
494 | if(!AllocInstruments()) return 0; | ||
495 | d=of.instruments; | ||
496 | |||
497 | for(oldnumsmp=t=0;t<of.numins;t++) { | ||
498 | IMFINSTHEADER ih; | ||
499 | |||
500 | memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD)); | ||
501 | |||
502 | /* read instrument header */ | ||
503 | _mm_read_string(ih.name,32,modreader); | ||
504 | d->insname=DupStr(ih.name,31,1); | ||
505 | _mm_read_UBYTES(ih.what,IMFNOTECNT,modreader); | ||
506 | _mm_fseek(modreader,8,SEEK_CUR); | ||
507 | _mm_read_I_UWORDS(ih.volenv,IMFENVCNT,modreader); | ||
508 | _mm_read_I_UWORDS(ih.panenv,IMFENVCNT,modreader); | ||
509 | _mm_read_I_UWORDS(ih.pitenv,IMFENVCNT,modreader); | ||
510 | |||
511 | #if defined __STDC__ || defined _MSC_VER || defined MPW_C | ||
512 | #define IMF_FinishLoadingEnvelope(name) \ | ||
513 | ih. name##pts=_mm_read_UBYTE(modreader); \ | ||
514 | ih. name##sus=_mm_read_UBYTE(modreader); \ | ||
515 | ih. name##beg=_mm_read_UBYTE(modreader); \ | ||
516 | ih. name##end=_mm_read_UBYTE(modreader); \ | ||
517 | ih. name##flg=_mm_read_UBYTE(modreader); \ | ||
518 | _mm_read_UBYTE(modreader); \ | ||
519 | _mm_read_UBYTE(modreader); \ | ||
520 | _mm_read_UBYTE(modreader) | ||
521 | #else | ||
522 | #define IMF_FinishLoadingEnvelope(name) \ | ||
523 | ih. name/**/pts=_mm_read_UBYTE(modreader); \ | ||
524 | ih. name/**/sus=_mm_read_UBYTE(modreader); \ | ||
525 | ih. name/**/beg=_mm_read_UBYTE(modreader); \ | ||
526 | ih. name/**/end=_mm_read_UBYTE(modreader); \ | ||
527 | ih. name/**/flg=_mm_read_UBYTE(modreader); \ | ||
528 | _mm_read_UBYTE(modreader); \ | ||
529 | _mm_read_UBYTE(modreader); \ | ||
530 | _mm_read_UBYTE(modreader) | ||
531 | #endif | ||
532 | |||
533 | IMF_FinishLoadingEnvelope(vol); | ||
534 | IMF_FinishLoadingEnvelope(pan); | ||
535 | IMF_FinishLoadingEnvelope(pit); | ||
536 | |||
537 | ih.volfade=_mm_read_I_UWORD(modreader); | ||
538 | ih.numsmp =_mm_read_I_UWORD(modreader); | ||
539 | |||
540 | _mm_read_UBYTES(id,4,modreader); | ||
541 | /* Looks like Imago Orpheus forgets the signature for empty | ||
542 | instruments following a multi-sample instrument... */ | ||
543 | if(memcmp(id,"II10",4) && | ||
544 | (oldnumsmp && memcmp(id,"\x0\x0\x0\x0",4))) { | ||
545 | if(nextwav) MikMod_free(nextwav); | ||
546 | if(wh) MikMod_free(wh); | ||
547 | _mm_errno=MMERR_LOADING_SAMPLEINFO; | ||
548 | return 0; | ||
549 | } | ||
550 | oldnumsmp=ih.numsmp; | ||
551 | |||
552 | if((ih.numsmp>16)||(ih.volpts>IMFENVCNT/2)||(ih.panpts>IMFENVCNT/2)|| | ||
553 | (ih.pitpts>IMFENVCNT/2)||(_mm_eof(modreader))) { | ||
554 | if(nextwav) MikMod_free(nextwav); | ||
555 | if(wh) MikMod_free(wh); | ||
556 | _mm_errno=MMERR_LOADING_SAMPLEINFO; | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | for(u=0;u<IMFNOTECNT;u++) | ||
561 | d->samplenumber[u]=ih.what[u]>ih.numsmp?0xffff:ih.what[u]+of.numsmp; | ||
562 | d->volfade=ih.volfade; | ||
563 | |||
564 | #if defined __STDC__ || defined _MSC_VER || defined MPW_C | ||
565 | #define IMF_ProcessEnvelope(name) \ | ||
566 | for (u = 0; u < (IMFENVCNT >> 1); u++) { \ | ||
567 | d-> name##env[u].pos = ih. name##env[u << 1]; \ | ||
568 | d-> name##env[u].val = ih. name##env[(u << 1)+ 1]; \ | ||
569 | } \ | ||
570 | if (ih. name##flg&1) d-> name##flg|=EF_ON; \ | ||
571 | if (ih. name##flg&2) d-> name##flg|=EF_SUSTAIN; \ | ||
572 | if (ih. name##flg&4) d-> name##flg|=EF_LOOP; \ | ||
573 | d-> name##susbeg=d-> name##susend=ih. name##sus; \ | ||
574 | d-> name##beg=ih. name##beg; \ | ||
575 | d-> name##end=ih. name##end; \ | ||
576 | d-> name##pts=ih. name##pts; \ | ||
577 | \ | ||
578 | if ((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \ | ||
579 | d-> name##flg&=~EF_ON | ||
580 | #else | ||
581 | #define IMF_ProcessEnvelope(name) \ | ||
582 | for (u = 0; u < (IMFENVCNT >> 1); u++) { \ | ||
583 | d-> name/**/env[u].pos = ih. name/**/env[u << 1]; \ | ||
584 | d-> name/**/env[u].val = ih. name/**/env[(u << 1)+ 1]; \ | ||
585 | } \ | ||
586 | if (ih. name/**/flg&1) d-> name/**/flg|=EF_ON; \ | ||
587 | if (ih. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN; \ | ||
588 | if (ih. name/**/flg&4) d-> name/**/flg|=EF_LOOP; \ | ||
589 | d-> name/**/susbeg=d-> name/**/susend=ih. name/**/sus; \ | ||
590 | d-> name/**/beg=ih. name/**/beg; \ | ||
591 | d-> name/**/end=ih. name/**/end; \ | ||
592 | d-> name/**/pts=ih. name/**/pts; \ | ||
593 | \ | ||
594 | if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \ | ||
595 | d-> name/**/flg&=~EF_ON | ||
596 | #endif | ||
597 | |||
598 | IMF_ProcessEnvelope(vol); | ||
599 | IMF_ProcessEnvelope(pan); | ||
600 | IMF_ProcessEnvelope(pit); | ||
601 | #undef IMF_ProcessEnvelope | ||
602 | |||
603 | if(ih.pitflg&1) { | ||
604 | d->pitflg&=~EF_ON; | ||
605 | #ifdef MIKMOD_DEBUG | ||
606 | fprintf(stderr, "\rFilter envelopes not supported yet\n"); | ||
607 | #endif | ||
608 | } | ||
609 | |||
610 | /* gather sample information */ | ||
611 | for(u=0;u<ih.numsmp;u++,s++) { | ||
612 | /* allocate more room for sample information if necessary */ | ||
613 | if(of.numsmp+u==wavcnt) { | ||
614 | wavcnt+=IMF_SMPINCR; | ||
615 | if(!(nextwav=MikMod_realloc(nextwav,wavcnt*sizeof(ULONG)))) { | ||
616 | if(wh) MikMod_free(wh); | ||
617 | _mm_errno=MMERR_OUT_OF_MEMORY; | ||
618 | return 0; | ||
619 | } | ||
620 | if(!(wh=MikMod_realloc(wh,wavcnt*sizeof(IMFWAVHEADER)))) { | ||
621 | MikMod_free(nextwav); | ||
622 | _mm_errno=MMERR_OUT_OF_MEMORY; | ||
623 | return 0; | ||
624 | } | ||
625 | s=wh+(wavcnt-IMF_SMPINCR); | ||
626 | } | ||
627 | |||
628 | _mm_read_string(s->samplename,13,modreader); | ||
629 | _mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader); | ||
630 | s->length =_mm_read_I_ULONG(modreader); | ||
631 | s->loopstart =_mm_read_I_ULONG(modreader); | ||
632 | s->loopend =_mm_read_I_ULONG(modreader); | ||
633 | s->samplerate=_mm_read_I_ULONG(modreader); | ||
634 | s->volume =_mm_read_UBYTE(modreader)&0x7f; | ||
635 | s->pan =_mm_read_UBYTE(modreader); | ||
636 | _mm_fseek(modreader,14,SEEK_CUR); | ||
637 | s->flags =_mm_read_UBYTE(modreader); | ||
638 | _mm_fseek(modreader,11,SEEK_CUR); | ||
639 | _mm_read_UBYTES(id,4,modreader); | ||
640 | if(((memcmp(id,"IS10",4))&&(memcmp(id,"IW10",4)))|| | ||
641 | (_mm_eof(modreader))) { | ||
642 | MikMod_free(nextwav);MikMod_free(wh); | ||
643 | _mm_errno=MMERR_LOADING_SAMPLEINFO; | ||
644 | return 0; | ||
645 | } | ||
646 | nextwav[of.numsmp+u]=_mm_ftell(modreader); | ||
647 | _mm_fseek(modreader,s->length,SEEK_CUR); | ||
648 | } | ||
649 | |||
650 | of.numsmp+=ih.numsmp; | ||
651 | d++; | ||
652 | } | ||
653 | |||
654 | /* sanity check */ | ||
655 | if(!of.numsmp) { | ||
656 | if(nextwav) MikMod_free(nextwav); | ||
657 | if(wh) MikMod_free(wh); | ||
658 | _mm_errno=MMERR_LOADING_SAMPLEINFO; | ||
659 | return 0; | ||
660 | } | ||
661 | |||
662 | /* load samples */ | ||
663 | if(!AllocSamples()) { | ||
664 | MikMod_free(nextwav);MikMod_free(wh); | ||
665 | return 0; | ||
666 | } | ||
667 | if(!AllocLinear()) { | ||
668 | MikMod_free(nextwav);MikMod_free(wh); | ||
669 | return 0; | ||
670 | } | ||
671 | q=of.samples; | ||
672 | s=wh; | ||
673 | for(u=0;u<of.numsmp;u++,s++,q++) { | ||
674 | q->samplename=DupStr(s->samplename,12,1); | ||
675 | q->length =s->length; | ||
676 | q->loopstart=s->loopstart; | ||
677 | q->loopend =s->loopend; | ||
678 | q->volume =s->volume; | ||
679 | q->speed =s->samplerate; | ||
680 | if(of.flags&UF_LINEAR) | ||
681 | q->speed=speed_to_finetune(s->samplerate<<1,u); | ||
682 | q->panning =s->pan; | ||
683 | q->seekpos =nextwav[u]; | ||
684 | |||
685 | q->flags|=SF_SIGNED; | ||
686 | if(s->flags&0x1) q->flags|=SF_LOOP; | ||
687 | if(s->flags&0x2) q->flags|=SF_BIDI; | ||
688 | if(s->flags&0x8) q->flags|=SF_OWNPAN; | ||
689 | if(s->flags&0x4) { | ||
690 | q->flags|=SF_16BITS; | ||
691 | q->length >>=1; | ||
692 | q->loopstart>>=1; | ||
693 | q->loopend >>=1; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | d=of.instruments; | ||
698 | s=wh; | ||
699 | for(u=0;u<of.numins;u++,d++) { | ||
700 | for(t=0;t<IMFNOTECNT;t++) { | ||
701 | if(d->samplenumber[t]>=of.numsmp) | ||
702 | d->samplenote[t]=255; | ||
703 | else if (of.flags&UF_LINEAR) { | ||
704 | int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]]; | ||
705 | d->samplenote[u]=(note<0)?0:(note>255?255:note); | ||
706 | } else | ||
707 | d->samplenote[t]=t; | ||
708 | } | ||
709 | } | ||
710 | |||
711 | MikMod_free(wh);MikMod_free(nextwav); | ||
712 | return 1; | ||
713 | } | ||
714 | |||
715 | CHAR *IMF_LoadTitle(void) | ||
716 | { | ||
717 | CHAR s[31]; | ||
718 | |||
719 | _mm_fseek(modreader,0,SEEK_SET); | ||
720 | if(!_mm_read_UBYTES(s,31,modreader)) return NULL; | ||
721 | |||
722 | return(DupStr(s,31,1)); | ||
723 | } | ||
724 | |||
725 | /*========== Loader information */ | ||
726 | |||
727 | MIKMODAPI MLOADER load_imf={ | ||
728 | NULL, | ||
729 | "IMF", | ||
730 | "IMF (Imago Orpheus)", | ||
731 | IMF_Init, | ||
732 | IMF_Test, | ||
733 | IMF_Load, | ||
734 | IMF_Cleanup, | ||
735 | IMF_LoadTitle | ||
736 | }; | ||
737 | |||
738 | /* ex:set ts=4: */ | ||