Add "MikMod for Rockbox 0.1" from 2007-06-29
[mikmod-rockbox.git] / apps / plugins / mikmod / loaders / load_it.c
1 /*      MikMod sound library\r
2         (c) 1998, 1999, 2000, 2001, 2002 Miodrag Vallat and others - see file\r
3         AUTHORS for complete list.\r
4 \r
5         This library is free software; you can redistribute it and/or modify\r
6         it under the terms of the GNU Library General Public License as\r
7         published by the Free Software Foundation; either version 2 of\r
8         the License, or (at your option) any later version.\r
9  \r
10         This program is distributed in the hope that it will be useful,\r
11         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13         GNU Library General Public License for more details.\r
14  \r
15         You should have received a copy of the GNU Library General Public\r
16         License along with this library; if not, write to the Free Software\r
17         Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA\r
18         02111-1307, USA.\r
19 */\r
20 \r
21 /*==============================================================================\r
22 \r
23   $Id: load_it.c,v 1.2 2004/02/06 19:29:03 raph Exp $\r
24 \r
25   Impulse tracker (IT) module loader\r
26 \r
27 ==============================================================================*/\r
28 \r
29 #ifdef HAVE_CONFIG_H\r
30 #include "config.h"\r
31 #endif\r
32 \r
33 #ifdef HAVE_UNISTD_H\r
34 #include <unistd.h>\r
35 #endif\r
36 \r
37 //#include <ctype.h>\r
38 #include <stdio.h>\r
39 #ifdef HAVE_MEMORY_H\r
40 #include <memory.h>\r
41 #endif\r
42 #include <string.h>\r
43 \r
44 #include "mikmod_internals.h"\r
45 \r
46 #ifdef SUNOS\r
47 extern int fprintf(FILE *, const char *, ...);\r
48 extern int toupper(int);\r
49 #endif\r
50 \r
51 /*========== Module structure */\r
52 \r
53 /* header */\r
54 typedef struct ITHEADER {\r
55         CHAR    songname[26];\r
56         UBYTE   blank01[2];\r
57         UWORD   ordnum;\r
58         UWORD   insnum;\r
59         UWORD   smpnum;\r
60         UWORD   patnum;\r
61         UWORD   cwt;            /* Created with tracker (y.xx = 0x0yxx) */\r
62         UWORD   cmwt;           /* Compatible with tracker ver > than val. */\r
63         UWORD   flags;\r
64         UWORD   special;        /* bit 0 set = song message attached */\r
65         UBYTE   globvol;\r
66         UBYTE   mixvol;         /* mixing volume [ignored] */\r
67         UBYTE   initspeed;\r
68         UBYTE   inittempo;\r
69         UBYTE   pansep;         /* panning separation between channels */\r
70         UBYTE   zerobyte;       \r
71         UWORD   msglength;\r
72         ULONG   msgoffset;\r
73         UBYTE   blank02[4];\r
74         UBYTE   pantable[64];\r
75         UBYTE   voltable[64];\r
76 } ITHEADER;\r
77 \r
78 /* sample information */\r
79 typedef struct ITSAMPLE {\r
80         CHAR    filename[12];\r
81         UBYTE   zerobyte;\r
82         UBYTE   globvol;\r
83         UBYTE   flag;\r
84         UBYTE   volume;\r
85         UBYTE   panning;\r
86         CHAR    sampname[28];\r
87         UWORD   convert;        /* sample conversion flag */\r
88         ULONG   length;\r
89         ULONG   loopbeg;\r
90         ULONG   loopend;\r
91         ULONG   c5spd;\r
92         ULONG   susbegin;\r
93         ULONG   susend;\r
94         ULONG   sampoffset;\r
95         UBYTE   vibspeed;\r
96         UBYTE   vibdepth;\r
97         UBYTE   vibrate;\r
98         UBYTE   vibwave;        /* 0=sine, 1=rampdown, 2=square, 3=random (speed ignored) */\r
99 } ITSAMPLE;\r
100 \r
101 /* instrument information */\r
102 \r
103 #define ITENVCNT 25\r
104 #define ITNOTECNT 120\r
105 typedef struct ITINSTHEADER {\r
106         ULONG   size;                   /* (dword) Instrument size */\r
107         CHAR    filename[12];   /* (char) Instrument filename */\r
108         UBYTE   zerobyte;               /* (byte) Instrument type (always 0) */\r
109         UBYTE   volflg;\r
110         UBYTE   volpts;   \r
111         UBYTE   volbeg;                 /* (byte) Volume loop start (node) */\r
112         UBYTE   volend;                 /* (byte) Volume loop end (node) */\r
113         UBYTE   volsusbeg;              /* (byte) Volume sustain begin (node) */\r
114         UBYTE   volsusend;              /* (byte) Volume Sustain end (node) */\r
115         UBYTE   panflg;\r
116         UBYTE   panpts;  \r
117         UBYTE   panbeg;                 /* (byte) channel loop start (node) */\r
118         UBYTE   panend;                 /* (byte) channel loop end (node) */\r
119         UBYTE   pansusbeg;              /* (byte) channel sustain begin (node) */\r
120         UBYTE   pansusend;              /* (byte) channel Sustain end (node) */\r
121         UBYTE   pitflg;\r
122         UBYTE   pitpts;   \r
123         UBYTE   pitbeg;                 /* (byte) pitch loop start (node) */\r
124         UBYTE   pitend;                 /* (byte) pitch loop end (node) */\r
125         UBYTE   pitsusbeg;              /* (byte) pitch sustain begin (node) */\r
126         UBYTE   pitsusend;              /* (byte) pitch Sustain end (node) */\r
127         UWORD   blank;\r
128         UBYTE   globvol;\r
129         UBYTE   chanpan;\r
130         UWORD   fadeout;                /* Envelope end / NNA volume fadeout */\r
131         UBYTE   dnc;                    /* Duplicate note check */\r
132         UBYTE   dca;                    /* Duplicate check action */\r
133         UBYTE   dct;                    /* Duplicate check type */\r
134         UBYTE   nna;                    /* New Note Action [0,1,2,3] */\r
135         UWORD   trkvers;                /* tracker version used to save [files only] */\r
136         UBYTE   ppsep;                  /* Pitch-pan Separation */\r
137         UBYTE   ppcenter;               /* Pitch-pan Center */\r
138         UBYTE   rvolvar;                /* random volume varations */\r
139         UBYTE   rpanvar;                /* random panning varations */\r
140         UWORD   numsmp;                 /* Number of samples in instrument [files only] */\r
141         CHAR    name[26];               /* Instrument name */\r
142         UBYTE   blank01[6];\r
143         UWORD   samptable[ITNOTECNT];/* sample for each note [note / samp pairs] */\r
144         UBYTE   volenv[200];         /* volume envelope (IT 1.x stuff) */\r
145         UBYTE   oldvoltick[ITENVCNT];/* volume tick position (IT 1.x stuff) */\r
146         UBYTE   volnode[ITENVCNT];   /* amplitude of volume nodes */\r
147         UWORD   voltick[ITENVCNT];   /* tick value of volume nodes */\r
148         SBYTE   pannode[ITENVCNT];   /* panenv - node points */\r
149         UWORD   pantick[ITENVCNT];   /* tick value of panning nodes */\r
150         SBYTE   pitnode[ITENVCNT];   /* pitchenv - node points */\r
151         UWORD   pittick[ITENVCNT];   /* tick value of pitch nodes */\r
152 } ITINSTHEADER;                       \r
153 \r
154 /* unpacked note */\r
155 \r
156 typedef struct ITNOTE {\r
157         UBYTE note,ins,volpan,cmd,inf;\r
158 } ITNOTE;\r
159 \r
160 /*========== Loader data */\r
161 \r
162 static ULONG *paraptr=NULL;     /* parapointer array (see IT docs) */\r
163 static ITHEADER *mh=NULL;\r
164 static ITNOTE *itpat=NULL;      /* allocate to space for one full pattern */\r
165 static UBYTE *mask=NULL;        /* arrays allocated to 64 elements and used for */\r
166 static ITNOTE *last=NULL;       /* uncompressing IT's pattern information */\r
167 static int numtrk=0;\r
168 static unsigned int old_effect;         /* if set, use S3M old-effects stuffs */\r
169    \r
170 static CHAR* IT_Version[]={\r
171         "ImpulseTracker  .  ",\r
172         "Compressed ImpulseTracker  .  ",\r
173         "ImpulseTracker 2.14p3",\r
174         "Compressed ImpulseTracker 2.14p3",\r
175         "ImpulseTracker 2.14p4",\r
176         "Compressed ImpulseTracker 2.14p4",\r
177 };\r
178 \r
179 /* table for porta-to-note command within volume/panning column */\r
180 static UBYTE portatable[10]= {0,1,4,8,16,32,64,96,128,255};\r
181 \r
182 /*========== Loader code */\r
183 \r
184 BOOL IT_Test(void)\r
185 {\r
186         UBYTE id[4];\r
187 \r
188         if(!_mm_read_UBYTES(id,4,modreader)) return 0;\r
189         if(!memcmp(id,"IMPM",4)) return 1;\r
190         return 0;\r
191 }\r
192 \r
193 BOOL IT_Init(void)\r
194 {\r
195         if(!(mh=(ITHEADER*)_mm_malloc(sizeof(ITHEADER)))) return 0;\r
196         if(!(poslookup=(UBYTE*)_mm_malloc(256*sizeof(UBYTE)))) return 0;\r
197         if(!(itpat=(ITNOTE*)_mm_malloc(200*64*sizeof(ITNOTE)))) return 0;\r
198         if(!(mask=(UBYTE*)_mm_malloc(64*sizeof(UBYTE)))) return 0;\r
199         if(!(last=(ITNOTE*)_mm_malloc(64*sizeof(ITNOTE)))) return 0;\r
200 \r
201         return 1;\r
202 }\r
203 \r
204 void IT_Cleanup(void)\r
205 {\r
206         FreeLinear();\r
207 \r
208         _mm_free(mh);\r
209         _mm_free(poslookup);\r
210         _mm_free(itpat);\r
211         _mm_free(mask);\r
212         _mm_free(last);\r
213         _mm_free(paraptr);\r
214         _mm_free(origpositions);\r
215 }\r
216 \r
217 /* Because so many IT files have 64 channels as the set number used, but really\r
218    only use far less (usually from 8 to 24 still), I had to make this function,\r
219    which determines the number of channels that are actually USED by a pattern.\r
220  \r
221    NOTE: You must first seek to the file location of the pattern before calling\r
222          this procedure.\r
223 \r
224    Returns 1 on error\r
225 */\r
226 static BOOL IT_GetNumChannels(UWORD patrows)\r
227 {\r
228         int row=0,flag,ch;\r
229 \r
230         do {\r
231                 if((flag=_mm_read_UBYTE(modreader))==EOF) {\r
232                         _mm_errno=MMERR_LOADING_PATTERN;\r
233                         return 1;\r
234                 }\r
235                 if(!flag)\r
236                         row++;\r
237                 else {\r
238                         ch=(flag-1)&63;\r
239                         remap[ch]=0;\r
240                         if(flag & 128) mask[ch]=_mm_read_UBYTE(modreader);\r
241                         if(mask[ch]&1)   _mm_read_UBYTE(modreader);\r
242                         if(mask[ch]&2)   _mm_read_UBYTE(modreader);\r
243                         if(mask[ch]&4)   _mm_read_UBYTE(modreader);\r
244                         if(mask[ch]&8) { _mm_read_UBYTE(modreader);_mm_read_UBYTE(modreader); }\r
245                 }\r
246         } while(row<patrows);\r
247 \r
248         return 0;\r
249 }\r
250 \r
251 static UBYTE* IT_ConvertTrack(ITNOTE* tr,UWORD numrows)\r
252 {\r
253         int t;\r
254         UBYTE note,ins,volpan;\r
255 \r
256         UniReset();\r
257 \r
258         for(t=0;t<numrows;t++) {\r
259                 note=tr[t*of.numchn].note;\r
260                 ins=tr[t*of.numchn].ins;\r
261                 volpan=tr[t*of.numchn].volpan;\r
262 \r
263                 if(note!=255) {\r
264                         if(note==253)\r
265                                 UniWriteByte(UNI_KEYOFF);\r
266                         else if(note==254) {\r
267                                 UniPTEffect(0xc,-1);    /* note cut command */\r
268                                 volpan=255;\r
269                         } else\r
270                                 UniNote(note);\r
271                 }\r
272 \r
273                 if((ins)&&(ins<100))\r
274                         UniInstrument(ins-1);\r
275                 else if(ins==253)\r
276                         UniWriteByte(UNI_KEYOFF);\r
277                 else if(ins!=255) { /* crap */\r
278                         _mm_errno=MMERR_LOADING_PATTERN;\r
279                         return NULL;\r
280                 }\r
281 \r
282                 /* process volume / panning column\r
283                    volume / panning effects do NOT all share the same memory address\r
284                    yet. */\r
285                 if(volpan<=64) \r
286                         UniVolEffect(VOL_VOLUME,volpan);\r
287                 else if(volpan==65) /* fine volume slide up (65-74) - A0 case */\r
288                         UniVolEffect(VOL_VOLSLIDE,0);\r
289                 else if(volpan<=74)     { /* fine volume slide up (65-74) - general case */\r
290                         UniVolEffect(VOL_VOLSLIDE,0x0f+((volpan-65)<<4));\r
291                 } else if(volpan==75)   /* fine volume slide down (75-84) - B0 case */\r
292                         UniVolEffect(VOL_VOLSLIDE,0);\r
293                 else if(volpan<=84) {   /* fine volume slide down (75-84) - general case*/\r
294                         UniVolEffect(VOL_VOLSLIDE,0xf0+(volpan-75));\r
295                 } else if(volpan<=94)   /* volume slide up (85-94) */\r
296                         UniVolEffect(VOL_VOLSLIDE,((volpan-85)<<4));\r
297                 else if(volpan<=104)/* volume slide down (95-104) */\r
298                         UniVolEffect(VOL_VOLSLIDE,(volpan-95));\r
299                 else if(volpan<=114)/* pitch slide down (105-114) */\r
300                         UniVolEffect(VOL_PITCHSLIDEDN,(volpan-105));\r
301                 else if(volpan<=124)/* pitch slide up (115-124) */\r
302                         UniVolEffect(VOL_PITCHSLIDEUP,(volpan-115));\r
303                 else if(volpan<=127) { /* crap */\r
304                         _mm_errno=MMERR_LOADING_PATTERN;\r
305                         return NULL;\r
306                 } else if(volpan<=192)\r
307                         UniVolEffect(VOL_PANNING,((volpan-128)==64)?255:((volpan-128)<<2));\r
308                 else if(volpan<=202)/* portamento to note */\r
309                         UniVolEffect(VOL_PORTAMENTO,portatable[volpan-193]);\r
310                 else if(volpan<=212)/* vibrato */\r
311                         UniVolEffect(VOL_VIBRATO,(volpan-203));\r
312                 else if((volpan!=239)&&(volpan!=255)) { /* crap */\r
313                         _mm_errno=MMERR_LOADING_PATTERN;\r
314                         return NULL;\r
315                 }\r
316 \r
317                 S3MIT_ProcessCmd(tr[t*of.numchn].cmd,tr[t*of.numchn].inf,\r
318                     old_effect|S3MIT_IT);\r
319 \r
320                 UniNewline();\r
321         }\r
322         return UniDup();\r
323 }\r
324 \r
325 static BOOL IT_ReadPattern(UWORD patrows)\r
326 {\r
327         int row=0,flag,ch,blah;\r
328         ITNOTE *itt=itpat,dummy,*n,*l;\r
329 \r
330         memset(itt,255,200*64*sizeof(ITNOTE));\r
331 \r
332         do {\r
333                 if((flag=_mm_read_UBYTE(modreader))==EOF) {\r
334                         _mm_errno = MMERR_LOADING_PATTERN;\r
335                         return 0;\r
336                 }\r
337                 if(!flag) {\r
338                         itt=&itt[of.numchn];\r
339                         row++;\r
340                 } else {\r
341                         ch=remap[(flag-1)&63];\r
342                         if(ch!=-1) {\r
343                                 n=&itt[ch];\r
344                                 l=&last[ch];\r
345                         } else \r
346                                 n=l=&dummy;\r
347 \r
348                         if(flag&128) mask[ch]=_mm_read_UBYTE(modreader);\r
349                         if(mask[ch]&1)\r
350                                 /* convert IT note off to internal note off */\r
351                                 if((l->note=n->note=_mm_read_UBYTE(modreader))==255) \r
352                                         l->note=n->note=253;\r
353                         if(mask[ch]&2)\r
354                                 l->ins=n->ins=_mm_read_UBYTE(modreader);\r
355                         if(mask[ch]&4)\r
356                                 l->volpan=n->volpan=_mm_read_UBYTE(modreader);\r
357                         if(mask[ch]&8) {\r
358                                 l->cmd=n->cmd=_mm_read_UBYTE(modreader);\r
359                                 l->inf=n->inf=_mm_read_UBYTE(modreader);\r
360                         }\r
361                         if(mask[ch]&16)\r
362                                 n->note=l->note;\r
363                         if(mask[ch]&32)\r
364                                 n->ins=l->ins;\r
365                         if(mask[ch]&64)\r
366                                 n->volpan=l->volpan;\r
367                         if(mask[ch]&128) {\r
368                                 n->cmd=l->cmd;\r
369                                 n->inf=l->inf;\r
370                         }\r
371                 }\r
372         } while(row<patrows);\r
373 \r
374         for(blah=0;blah<of.numchn;blah++) {\r
375                 if(!(of.tracks[numtrk++]=IT_ConvertTrack(&itpat[blah],patrows)))\r
376                         return 0;\r
377         }\r
378 \r
379         return 1;\r
380 }\r
381 \r
382 static void LoadMidiString(MREADER* modreader,CHAR* dest)\r
383 {\r
384         CHAR *cur,*last;\r
385 \r
386         _mm_read_UBYTES(dest,32,modreader);\r
387         cur=last=dest;\r
388         /* remove blanks and uppercase all */\r
389         while(*last) {\r
390                 if(isalnum((int)*last)) *(cur++)=toupper((int)*last);\r
391                 last++;\r
392         }\r
393         *cur=0;\r
394 }\r
395 \r
396 /* Load embedded midi information for resonant filters */\r
397 static void IT_LoadMidiConfiguration(MREADER* modreader)\r
398 {\r
399         int i;\r
400 \r
401         memset(filtermacros,0,sizeof(filtermacros));\r
402         memset(filtersettings,0,sizeof(filtersettings));\r
403 \r
404         if (modreader) { /* information is embedded in file */\r
405                 UWORD dat;\r
406                 CHAR midiline[33];\r
407 \r
408                 dat=_mm_read_I_UWORD(modreader);\r
409                 _mm_fseek(modreader,8*dat+0x120,SEEK_CUR);\r
410 \r
411                 /* read midi macros */\r
412                 for(i=0;i<UF_MAXMACRO;i++) {\r
413                         LoadMidiString(modreader,midiline);\r
414                         if((!strncmp(midiline,"F0F00",5))&&\r
415                            ((midiline[5]=='0')||(midiline[5]=='1')))\r
416                                         filtermacros[i]=(midiline[5]-'0')|0x80;\r
417                 }\r
418 \r
419                 /* read standalone filters */\r
420                 for(i=0x80;i<0x100;i++) {\r
421                         LoadMidiString(modreader,midiline);\r
422                         if((!strncmp(midiline,"F0F00",5))&&\r
423                            ((midiline[5]=='0')||(midiline[5]=='1'))) {\r
424                                 filtersettings[i].filter=(midiline[5]-'0')|0x80;\r
425                                 dat=(midiline[6])?(midiline[6]-'0'):0;\r
426                                 if(midiline[7])dat=(dat<<4)|(midiline[7]-'0');\r
427                                 filtersettings[i].inf=dat;\r
428                         }\r
429                 }\r
430         } else { /* use default information */\r
431                 filtermacros[0]=FILT_CUT;\r
432                 for(i=0x80;i<0x90;i++) {\r
433                         filtersettings[i].filter=FILT_RESONANT;\r
434                         filtersettings[i].inf=(i&0x7f)<<3;\r
435                 }\r
436         }\r
437         activemacro=0;\r
438         for(i=0;i<0x80;i++) {\r
439                 filtersettings[i].filter=filtermacros[0];\r
440                 filtersettings[i].inf=i;\r
441         }\r
442 }\r
443 \r
444 BOOL IT_Load(BOOL curious)\r
445 {\r
446         int t,u,lp;\r
447         INSTRUMENT *d;\r
448         SAMPLE *q;\r
449         BOOL compressed=0;\r
450 \r
451         numtrk=0;\r
452         filters=0;\r
453 \r
454         /* try to read module header */\r
455         _mm_read_I_ULONG(modreader);    /* kill the 4 byte header */\r
456         _mm_read_string(mh->songname,26,modreader);\r
457         _mm_read_UBYTES(mh->blank01,2,modreader);\r
458         mh->ordnum      =_mm_read_I_UWORD(modreader);\r
459         mh->insnum      =_mm_read_I_UWORD(modreader);\r
460         mh->smpnum      =_mm_read_I_UWORD(modreader);\r
461         mh->patnum      =_mm_read_I_UWORD(modreader);\r
462         mh->cwt         =_mm_read_I_UWORD(modreader);\r
463         mh->cmwt        =_mm_read_I_UWORD(modreader);\r
464         mh->flags       =_mm_read_I_UWORD(modreader);\r
465         mh->special     =_mm_read_I_UWORD(modreader);\r
466         mh->globvol     =_mm_read_UBYTE(modreader);\r
467         mh->mixvol      =_mm_read_UBYTE(modreader);\r
468         mh->initspeed   =_mm_read_UBYTE(modreader);\r
469         mh->inittempo   =_mm_read_UBYTE(modreader);\r
470         mh->pansep      =_mm_read_UBYTE(modreader);\r
471         mh->zerobyte    =_mm_read_UBYTE(modreader);\r
472         mh->msglength   =_mm_read_I_UWORD(modreader);\r
473         mh->msgoffset   =_mm_read_I_ULONG(modreader);\r
474         _mm_read_UBYTES(mh->blank02,4,modreader);\r
475         _mm_read_UBYTES(mh->pantable,64,modreader);\r
476         _mm_read_UBYTES(mh->voltable,64,modreader);\r
477 \r
478         if(_mm_eof(modreader)) {\r
479                 _mm_errno=MMERR_LOADING_HEADER;\r
480                 return 0;\r
481         }\r
482 \r
483         /* set module variables */\r
484         of.songname    = DupStr(mh->songname,26,0); /* make a cstr of songname  */\r
485         of.reppos      = 0;\r
486         of.numpat      = mh->patnum;\r
487         of.numins      = mh->insnum;\r
488         of.numsmp      = mh->smpnum;\r
489         of.initspeed   = mh->initspeed;\r
490         of.inittempo   = mh->inittempo;\r
491         of.initvolume  = mh->globvol;\r
492         of.flags      |= UF_BGSLIDES | UF_ARPMEM;\r
493         if (!(mh->flags & 1))\r
494                         of.flags |= UF_PANNING;\r
495         of.bpmlimit=32;\r
496 \r
497         if(mh->songname[25]) {\r
498                 of.numvoices=1+mh->songname[25];\r
499 #ifdef MIKMOD_DEBUG\r
500                 fprintf(stderr,"Embedded IT limitation to %d voices\n",of.numvoices);\r
501 #endif\r
502         }\r
503 \r
504         /* set the module type */\r
505         /* 2.17 : IT 2.14p4 */\r
506         /* 2.16 : IT 2.14p3 with resonant filters */\r
507         /* 2.15 : IT 2.14p3 (improved compression) */\r
508         if((mh->cwt<=0x219)&&(mh->cwt>=0x217))\r
509                 of.modtype=strdup(IT_Version[mh->cmwt<0x214?4:5]);\r
510         else if (mh->cwt>=0x215)\r
511                 of.modtype=strdup(IT_Version[mh->cmwt<0x214?2:3]);\r
512         else {\r
513                 of.modtype     = strdup(IT_Version[mh->cmwt<0x214?0:1]);\r
514                 of.modtype[mh->cmwt<0x214?15:26] = (mh->cwt>>8)+'0';\r
515                 of.modtype[mh->cmwt<0x214?17:28] = ((mh->cwt>>4)&0xf)+'0';\r
516                 of.modtype[mh->cmwt<0x214?18:29] = ((mh->cwt)&0xf)+'0';\r
517         }\r
518 \r
519         if(mh->flags&8)\r
520                 of.flags |= UF_XMPERIODS | UF_LINEAR;\r
521 \r
522         if((mh->cwt>=0x106)&&(mh->flags&16))\r
523                 old_effect=S3MIT_OLDSTYLE;\r
524         else\r
525                 old_effect=0;\r
526 \r
527         /* set panning positions */\r
528         if (mh->flags & 1)\r
529                 for(t=0;t<64;t++) {\r
530                         mh->pantable[t]&=0x7f;\r
531                         if(mh->pantable[t]<64)\r
532                                 of.panning[t]=mh->pantable[t]<<2;\r
533                         else if(mh->pantable[t]==64)\r
534                                 of.panning[t]=255;\r
535                         else if(mh->pantable[t]==100)\r
536                                 of.panning[t]=PAN_SURROUND;\r
537                         else if(mh->pantable[t]==127)\r
538                                 of.panning[t]=PAN_CENTER;\r
539                         else {\r
540                                 _mm_errno=MMERR_LOADING_HEADER;\r
541                                 return 0;\r
542                         }\r
543                 }\r
544         else\r
545                 for(t=0;t<64;t++)\r
546                         of.panning[t]=PAN_CENTER;\r
547 \r
548         /* set channel volumes */\r
549         memcpy(of.chanvol,mh->voltable,64);\r
550 \r
551         /* read the order data */\r
552         if(!AllocPositions(mh->ordnum)) return 0;\r
553         if(!(origpositions=_mm_calloc(mh->ordnum,sizeof(UWORD)))) return 0;\r
554 \r
555         for(t=0;t<mh->ordnum;t++) {\r
556                 origpositions[t]=_mm_read_UBYTE(modreader);\r
557                 if((origpositions[t]>mh->patnum)&&(origpositions[t]<254))\r
558                         origpositions[t]=255;\r
559         }\r
560 \r
561         if(_mm_eof(modreader)) {\r
562                 _mm_errno = MMERR_LOADING_HEADER;\r
563                 return 0;\r
564         }\r
565 \r
566         poslookupcnt=mh->ordnum;\r
567         S3MIT_CreateOrders(curious);\r
568 \r
569         if(!(paraptr=(ULONG*)_mm_malloc((mh->insnum+mh->smpnum+of.numpat)*\r
570                                        sizeof(ULONG)))) return 0;\r
571 \r
572         /* read the instrument, sample, and pattern parapointers */\r
573         _mm_read_I_ULONGS(paraptr,mh->insnum+mh->smpnum+of.numpat,modreader);\r
574 \r
575         if(_mm_eof(modreader)) {\r
576                 _mm_errno = MMERR_LOADING_HEADER;\r
577                 return 0;\r
578         }\r
579 \r
580         /* Check for and load midi information for resonant filters */\r
581         if(mh->cmwt>=0x216) {\r
582                 if(mh->special&8) {\r
583                         IT_LoadMidiConfiguration(modreader);\r
584                         if(_mm_eof(modreader)) {\r
585                                 _mm_errno = MMERR_LOADING_HEADER;\r
586                                 return 0;\r
587                         }\r
588                 } else\r
589                         IT_LoadMidiConfiguration(NULL);\r
590                 filters=1;\r
591         }\r
592 \r
593         /* Check for and load song comment */\r
594         if((mh->special&1)&&(mh->cwt>=0x104)&&(mh->msglength)) {\r
595                 _mm_fseek(modreader,(long)(mh->msgoffset),SEEK_SET);\r
596                 if(!ReadComment(mh->msglength)) return 0;\r
597         }\r
598 \r
599         if(!(mh->flags&4)) of.numins=of.numsmp;\r
600         if(!AllocSamples()) return 0;\r
601 \r
602         if(!AllocLinear()) return 0;\r
603 \r
604         /* Load all samples */\r
605         q = of.samples;\r
606         for(t=0;t<mh->smpnum;t++) {\r
607                 ITSAMPLE s;\r
608 \r
609                 /* seek to sample position */\r
610                 _mm_fseek(modreader,(long)(paraptr[mh->insnum+t]+4),SEEK_SET);\r
611 \r
612                 /* load sample info */\r
613                 _mm_read_string(s.filename,12,modreader);\r
614                 s.zerobyte    = _mm_read_UBYTE(modreader);\r
615                 s.globvol     = _mm_read_UBYTE(modreader);\r
616                 s.flag        = _mm_read_UBYTE(modreader);\r
617                 s.volume      = _mm_read_UBYTE(modreader);\r
618                 _mm_read_string(s.sampname,26,modreader);\r
619                 s.convert     = _mm_read_UBYTE(modreader);\r
620                 s.panning     = _mm_read_UBYTE(modreader);\r
621                 s.length      = _mm_read_I_ULONG(modreader);\r
622                 s.loopbeg     = _mm_read_I_ULONG(modreader);\r
623                 s.loopend     = _mm_read_I_ULONG(modreader);\r
624                 s.c5spd       = _mm_read_I_ULONG(modreader);\r
625                 s.susbegin    = _mm_read_I_ULONG(modreader);\r
626                 s.susend      = _mm_read_I_ULONG(modreader);\r
627                 s.sampoffset  = _mm_read_I_ULONG(modreader);\r
628                 s.vibspeed    = _mm_read_UBYTE(modreader);\r
629                 s.vibdepth    = _mm_read_UBYTE(modreader);\r
630                 s.vibrate     = _mm_read_UBYTE(modreader);\r
631                 s.vibwave     = _mm_read_UBYTE(modreader);\r
632 \r
633                 /* Generate an error if c5spd is > 512k, or samplelength > 256 megs\r
634                    (nothing would EVER be that high) */\r
635 \r
636                 if(_mm_eof(modreader)||(s.c5spd>0x7ffffL)||(s.length>0xfffffffUL)) {\r
637                         _mm_errno = MMERR_LOADING_SAMPLEINFO;\r
638                         return 0;\r
639                 }\r
640 \r
641                 /* Reality check for sample loop information */\r
642                 if((s.flag&16)&&\r
643                    ((s.loopbeg>0xfffffffUL)||(s.loopend>0xfffffffUL))) {\r
644                         _mm_errno = MMERR_LOADING_SAMPLEINFO;\r
645                         return 0;\r
646                 }\r
647 \r
648                 q->samplename = DupStr(s.sampname,26,0);\r
649                 q->speed      = s.c5spd / 2;\r
650                 q->panning    = ((s.panning&127)==64)?255:(s.panning&127)<<2;\r
651                 q->length     = s.length;\r
652                 q->loopstart  = s.loopbeg;\r
653                 q->loopend    = s.loopend;\r
654                 q->volume     = s.volume;\r
655                 q->globvol    = s.globvol;\r
656                 q->seekpos    = s.sampoffset;\r
657 \r
658                 /* Convert speed to XM linear finetune */\r
659                 if(of.flags&UF_LINEAR)\r
660                         q->speed=speed_to_finetune(s.c5spd,t);\r
661 \r
662                 if(s.panning&128) q->flags|=SF_OWNPAN;\r
663 \r
664                 if(s.vibrate) {\r
665                         q->vibflags |= AV_IT;\r
666                         q->vibtype   = s.vibwave;\r
667                         q->vibsweep  = s.vibrate * 2;\r
668                         q->vibdepth  = s.vibdepth;\r
669                         q->vibrate   = s.vibspeed;\r
670                 }\r
671 \r
672                 if(s.flag&2) q->flags|=SF_16BITS;\r
673                 if((s.flag&8)&&(mh->cwt>=0x214)) {\r
674                         q->flags|=SF_ITPACKED;\r
675                         compressed=1;\r
676                 }\r
677                 if(s.flag&16) q->flags|=SF_LOOP;\r
678                 if(s.flag&64) q->flags|=SF_BIDI;\r
679 \r
680                 if(mh->cwt>=0x200) {\r
681                         if(s.convert&1) q->flags|=SF_SIGNED;\r
682                         if(s.convert&4) q->flags|=SF_DELTA;   \r
683                 }\r
684                 q++;\r
685         }\r
686 \r
687         /* Load instruments if instrument mode flag enabled */\r
688         if(mh->flags&4) {\r
689                 if(!AllocInstruments()) return 0;\r
690                 d=of.instruments;\r
691                 of.flags|=UF_NNA|UF_INST;\r
692 \r
693                 for(t=0;t<mh->insnum;t++) {\r
694                         ITINSTHEADER ih;\r
695 \r
696                         /* seek to instrument position */\r
697                         _mm_fseek(modreader,paraptr[t]+4,SEEK_SET);\r
698 \r
699                         /* load instrument info */\r
700                         _mm_read_string(ih.filename,12,modreader);\r
701                         ih.zerobyte  = _mm_read_UBYTE(modreader);\r
702                         if(mh->cwt<0x200) {\r
703                                 /* load IT 1.xx inst header */\r
704                                 ih.volflg    = _mm_read_UBYTE(modreader);\r
705                                 ih.volbeg    = _mm_read_UBYTE(modreader);\r
706                                 ih.volend    = _mm_read_UBYTE(modreader);\r
707                                 ih.volsusbeg = _mm_read_UBYTE(modreader);\r
708                                 ih.volsusend = _mm_read_UBYTE(modreader);\r
709                                 _mm_read_I_UWORD(modreader);\r
710                                 ih.fadeout   = _mm_read_I_UWORD(modreader);\r
711                                 ih.nna       = _mm_read_UBYTE(modreader);\r
712                                 ih.dnc       = _mm_read_UBYTE(modreader);\r
713                         } else {\r
714                                 /* Read IT200+ header */\r
715                                 ih.nna       = _mm_read_UBYTE(modreader);\r
716                                 ih.dct       = _mm_read_UBYTE(modreader);\r
717                                 ih.dca       = _mm_read_UBYTE(modreader);\r
718                                 ih.fadeout   = _mm_read_I_UWORD(modreader);\r
719                                 ih.ppsep     = _mm_read_UBYTE(modreader);\r
720                                 ih.ppcenter  = _mm_read_UBYTE(modreader);\r
721                                 ih.globvol   = _mm_read_UBYTE(modreader);\r
722                                 ih.chanpan   = _mm_read_UBYTE(modreader);\r
723                                 ih.rvolvar   = _mm_read_UBYTE(modreader);\r
724                                 ih.rpanvar   = _mm_read_UBYTE(modreader);\r
725                         }\r
726 \r
727                         ih.trkvers   = _mm_read_I_UWORD(modreader);\r
728                         ih.numsmp    = _mm_read_UBYTE(modreader);\r
729                         _mm_read_UBYTE(modreader);\r
730                         _mm_read_string(ih.name,26,modreader);\r
731                         _mm_read_UBYTES(ih.blank01,6,modreader);\r
732                         _mm_read_I_UWORDS(ih.samptable,ITNOTECNT,modreader);\r
733                         if(mh->cwt<0x200) {\r
734                                 /* load IT 1xx volume envelope */\r
735                                 _mm_read_UBYTES(ih.volenv,200,modreader);\r
736                                 for(lp=0;lp<ITENVCNT;lp++) {\r
737                                         ih.oldvoltick[lp] = _mm_read_UBYTE(modreader);\r
738                                         ih.volnode[lp]    = _mm_read_UBYTE(modreader);\r
739                                 } \r
740                         } else {\r
741                                 /* load IT 2xx volume, pan and pitch envelopes */\r
742 #if defined __STDC__ || defined _MSC_VER || defined MPW_C\r
743 #define IT_LoadEnvelope(name,type)                                                                              \\r
744                                 ih. name##flg   =_mm_read_UBYTE(modreader);                             \\r
745                                 ih. name##pts   =_mm_read_UBYTE(modreader);                             \\r
746                                 ih. name##beg   =_mm_read_UBYTE(modreader);                             \\r
747                                 ih. name##end   =_mm_read_UBYTE(modreader);                             \\r
748                                 ih. name##susbeg=_mm_read_UBYTE(modreader);                             \\r
749                                 ih. name##susend=_mm_read_UBYTE(modreader);                             \\r
750                                 for(lp=0;lp<ITENVCNT;lp++) {                                                    \\r
751                                         ih. name##node[lp]=_mm_read_##type (modreader);         \\r
752                                         ih. name##tick[lp]=_mm_read_I_UWORD(modreader);         \\r
753                                 }                                                                                                               \\r
754                                 _mm_read_UBYTE(modreader)\r
755 #else\r
756 #define IT_LoadEnvelope(name,type)                                                                              \\r
757                                 ih. name/**/flg   =_mm_read_UBYTE(modreader);                   \\r
758                                 ih. name/**/pts   =_mm_read_UBYTE(modreader);                   \\r
759                                 ih. name/**/beg   =_mm_read_UBYTE(modreader);                   \\r
760                                 ih. name/**/end   =_mm_read_UBYTE(modreader);                   \\r
761                                 ih. name/**/susbeg=_mm_read_UBYTE(modreader);                   \\r
762                                 ih. name/**/susend=_mm_read_UBYTE(modreader);                   \\r
763                                 for(lp=0;lp<ITENVCNT;lp++) {                                                    \\r
764                                         ih. name/**/node[lp]=_mm_read_/**/type (modreader);     \\r
765                                         ih. name/**/tick[lp]=_mm_read_I_UWORD(modreader);       \\r
766                                 }                                                                                                               \\r
767                                 _mm_read_UBYTE(modreader)\r
768 #endif\r
769 \r
770                                 IT_LoadEnvelope(vol,UBYTE);\r
771                                 IT_LoadEnvelope(pan,SBYTE);\r
772                                 IT_LoadEnvelope(pit,SBYTE);\r
773 #undef IT_LoadEnvelope\r
774                         }\r
775  \r
776                         if(_mm_eof(modreader)) {\r
777                                 _mm_errno = MMERR_LOADING_SAMPLEINFO;\r
778                                 return 0;\r
779                         }\r
780 \r
781                         d->volflg|=EF_VOLENV;\r
782                         d->insname = DupStr(ih.name,26,0);\r
783                         d->nnatype = ih.nna & NNA_MASK;\r
784 \r
785                         if(mh->cwt<0x200) {\r
786                                 d->volfade=ih.fadeout<< 6;\r
787                                 if(ih.dnc) {\r
788                                         d->dct=DCT_NOTE;\r
789                                         d->dca=DCA_CUT;\r
790                                 }\r
791 \r
792                                 if(ih.volflg&1) d->volflg|=EF_ON;\r
793                                 if(ih.volflg&2) d->volflg|=EF_LOOP;\r
794                                 if(ih.volflg&4) d->volflg|=EF_SUSTAIN;      \r
795 \r
796                                 /* XM conversion of IT envelope Array */\r
797                                 d->volbeg    = ih.volbeg;   \r
798                                 d->volend    = ih.volend;\r
799                                 d->volsusbeg = ih.volsusbeg;\r
800                                 d->volsusend = ih.volsusend;\r
801 \r
802                                 if(ih.volflg&1) {\r
803                                         for(u=0;u<ITENVCNT;u++)\r
804                                                 if(ih.oldvoltick[d->volpts]!=0xff) {\r
805                                                         d->volenv[d->volpts].val=(ih.volnode[d->volpts]<<2);\r
806                                                         d->volenv[d->volpts].pos=ih.oldvoltick[d->volpts];\r
807                                                         d->volpts++;\r
808                                                 } else\r
809                                                         break;\r
810                                 }  \r
811                         } else {\r
812                                 d->panning=((ih.chanpan&127)==64)?255:(ih.chanpan&127)<<2;\r
813                                 if(!(ih.chanpan&128)) d->flags|=IF_OWNPAN;\r
814 \r
815                                 if(!(ih.ppsep & 128)) {\r
816                                         d->pitpansep=ih.ppsep<<2;\r
817                                         d->pitpancenter=ih.ppcenter;\r
818                                         d->flags|=IF_PITCHPAN;\r
819                                 }\r
820                                 d->globvol=ih.globvol>>1;\r
821                                 d->volfade=ih.fadeout<<5;\r
822                                 d->dct    =ih.dct;\r
823                                 d->dca    =ih.dca;\r
824 \r
825                                 if(mh->cwt>=0x204) {\r
826                                         d->rvolvar = ih.rvolvar;\r
827                                         d->rpanvar = ih.rpanvar;\r
828                                 }\r
829 \r
830 #if defined __STDC__ || defined _MSC_VER || defined MPW_C\r
831 #define IT_ProcessEnvelope(name)                                                                                \\r
832                                 if(ih. name##flg&1) d-> name##flg|=EF_ON;                               \\r
833                                 if(ih. name##flg&2) d-> name##flg|=EF_LOOP;                             \\r
834                                 if(ih. name##flg&4) d-> name##flg|=EF_SUSTAIN;                  \\r
835                                 d-> name##pts=ih. name##pts;                                                    \\r
836                                 d-> name##beg=ih. name##beg;                                                    \\r
837                                 d-> name##end=ih. name##end;                                                    \\r
838                                 d-> name##susbeg=ih. name##susbeg;                                              \\r
839                                 d-> name##susend=ih. name##susend;                                              \\r
840                                                                                                                                                 \\r
841                                 for(u=0;u<ih. name##pts;u++)                                                    \\r
842                                         d-> name##env[u].pos=ih. name##tick[u];                         \\r
843                                                                                                                                                 \\r
844                                 if((d-> name##flg&EF_ON)&&(d-> name##pts<2))                    \\r
845                                         d-> name##flg&=~EF_ON\r
846 #else\r
847 #define IT_ProcessEnvelope(name)                                                                        \\r
848                                 if(ih. name/**/flg&1) d-> name/**/flg|=EF_ON;           \\r
849                                 if(ih. name/**/flg&2) d-> name/**/flg|=EF_LOOP;         \\r
850                                 if(ih. name/**/flg&4) d-> name/**/flg|=EF_SUSTAIN;      \\r
851                                 d-> name/**/pts=ih. name/**/pts;                                        \\r
852                                 d-> name/**/beg=ih. name/**/beg;                                        \\r
853                                 d-> name/**/end=ih. name/**/end;                                        \\r
854                                 d-> name/**/susbeg=ih. name/**/susbeg;                          \\r
855                                 d-> name/**/susend=ih. name/**/susend;                          \\r
856                                                                                                                                         \\r
857                                 for(u=0;u<ih. name/**/pts;u++)                                          \\r
858                                         d-> name/**/env[u].pos=ih. name/**/tick[u];             \\r
859                                                                                                                                         \\r
860                                 if((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2))        \\r
861                                         d-> name/**/flg&=~EF_ON\r
862 #endif\r
863 \r
864                                 IT_ProcessEnvelope(vol);\r
865                                 for(u=0;u<ih.volpts;u++)\r
866                                         d->volenv[u].val=(ih.volnode[u]<<2);\r
867 \r
868                                 IT_ProcessEnvelope(pan);\r
869                                 for(u=0;u<ih.panpts;u++)\r
870                                         d->panenv[u].val=\r
871                                           ih.pannode[u]==32?255:(ih.pannode[u]+32)<<2;\r
872 \r
873                                 IT_ProcessEnvelope(pit);\r
874                                 for(u=0;u<ih.pitpts;u++)\r
875                                         d->pitenv[u].val=ih.pitnode[u]+32;\r
876 #undef IT_ProcessEnvelope\r
877 \r
878                                 if(ih.pitflg&0x80) {\r
879                                         /* filter envelopes not supported yet */\r
880                                         d->pitflg&=~EF_ON;\r
881                                         ih.pitpts=ih.pitbeg=ih.pitend=0;\r
882 #ifdef MIKMOD_DEBUG\r
883                                         {\r
884                                                 static int warn=0;\r
885                                                 \r
886                                                 if(!warn)\r
887                                                         fprintf(stderr, "\rFilter envelopes not supported yet\n");\r
888                                                 warn=1;\r
889                                         }\r
890 #endif\r
891                                 }\r
892                         }\r
893 \r
894                         for(u=0;u<ITNOTECNT;u++) {\r
895                                 d->samplenote[u]=(ih.samptable[u]&255);\r
896                                 d->samplenumber[u]=\r
897                                   (ih.samptable[u]>>8)?((ih.samptable[u]>>8)-1):0xffff;\r
898                                 if(d->samplenumber[u]>=of.numsmp)\r
899                                         d->samplenote[u]=255;\r
900                                 else if (of.flags&UF_LINEAR) {\r
901                                         int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]];\r
902                                         d->samplenote[u]=(note<0)?0:(note>255?255:note);\r
903                                 }\r
904                         }\r
905 \r
906                         d++;                  \r
907                 }\r
908         } else if(of.flags & UF_LINEAR) {\r
909                 if(!AllocInstruments()) return 0;\r
910                 d=of.instruments;\r
911                 of.flags|=UF_INST;\r
912 \r
913                 for(t=0;t<mh->smpnum;t++,d++)\r
914                         for(u=0;u<ITNOTECNT;u++) {\r
915                                 if(d->samplenumber[u]>=of.numsmp)\r
916                                         d->samplenote[u]=255;\r
917                                 else {\r
918                                         int note=(int)d->samplenote[u]+noteindex[d->samplenumber[u]];\r
919                                         d->samplenote[u]=(note<0)?0:(note>255?255:note);\r
920                                 }\r
921                         }\r
922         }\r
923 \r
924         /* Figure out how many channels this song actually uses */\r
925         of.numchn=0;\r
926         memset(remap,-1,UF_MAXCHAN*sizeof(UBYTE));\r
927         for(t=0;t<of.numpat;t++) {\r
928                 UWORD packlen;\r
929 \r
930                 /* seek to pattern position */\r
931                 if(paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */\r
932                         _mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET);\r
933                         _mm_read_I_UWORD(modreader);\r
934                         /* read pattern length (# of rows)\r
935                            Impulse Tracker never creates patterns with less than 32 rows,\r
936                            but some other trackers do, so we only check for more than 256\r
937                            rows */\r
938                         packlen=_mm_read_I_UWORD(modreader);\r
939                         if(packlen>256) {\r
940                                 _mm_errno=MMERR_LOADING_PATTERN;\r
941                                 return 0;\r
942                         }\r
943                         _mm_read_I_ULONG(modreader);\r
944                         if(IT_GetNumChannels(packlen)) return 0;\r
945                 }\r
946         }\r
947 \r
948         /* give each of them a different number */\r
949         for(t=0;t<UF_MAXCHAN;t++) \r
950                 if(!remap[t])\r
951                         remap[t]=of.numchn++;\r
952 \r
953         of.numtrk = of.numpat*of.numchn;\r
954         if(of.numvoices)\r
955                 if (of.numvoices<of.numchn) of.numvoices=of.numchn;\r
956 \r
957         if(!AllocPatterns()) return 0;\r
958         if(!AllocTracks()) return 0;\r
959 \r
960         for(t=0;t<of.numpat;t++) {\r
961                 UWORD packlen;\r
962 \r
963                 /* seek to pattern position */\r
964                 if(!paraptr[mh->insnum+mh->smpnum+t]) { /* 0 -> empty 64 row pattern */\r
965                         of.pattrows[t]=64;\r
966                         for(u=0;u<of.numchn;u++) {\r
967                                 int k;\r
968 \r
969                                 UniReset();\r
970                                 for(k=0;k<64;k++) UniNewline();\r
971                                 of.tracks[numtrk++]=UniDup();\r
972                         }\r
973                 } else {\r
974                         _mm_fseek(modreader,((long)paraptr[mh->insnum+mh->smpnum+t]),SEEK_SET);\r
975                         packlen=_mm_read_I_UWORD(modreader);\r
976                         of.pattrows[t]=_mm_read_I_UWORD(modreader);\r
977                         _mm_read_I_ULONG(modreader);\r
978                         if(!IT_ReadPattern(of.pattrows[t])) return 0;\r
979                 }\r
980         }\r
981 \r
982         return 1;\r
983 }\r
984 \r
985 CHAR *IT_LoadTitle(void)\r
986 {\r
987         CHAR s[26];\r
988 \r
989         _mm_fseek(modreader,4,SEEK_SET);\r
990         if(!_mm_read_UBYTES(s,26,modreader)) return NULL;\r
991    \r
992         return(DupStr(s,26,0));\r
993 }\r
994 \r
995 /*========== Loader information */\r
996 \r
997 MIKMODAPI MLOADER load_it={\r
998         NULL,\r
999         "IT",\r
1000         "IT (Impulse Tracker)",\r
1001         IT_Init,\r
1002         IT_Test,\r
1003         IT_Load,\r
1004         IT_Cleanup,\r
1005         IT_LoadTitle\r
1006 };\r
1007 \r
1008 /* ex:set ts=4: */\r