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
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
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
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
21 /*==============================================================================
\r
23 $Id: load_xm.c,v 1.2 2004/02/06 19:29:03 raph Exp $
\r
25 Fasttracker (XM) module loader
\r
27 ==============================================================================*/
\r
29 #ifdef HAVE_CONFIG_H
\r
33 #ifdef HAVE_UNISTD_H
\r
38 #ifdef HAVE_MEMORY_H
\r
43 #include "mikmod_internals.h"
\r
46 extern int fprintf(FILE *, const char *, ...);
\r
49 /*========== Module structure */
\r
51 typedef struct XMHEADER {
\r
52 CHAR id[17]; /* ID text: 'Extended module: ' */
\r
53 CHAR songname[21]; /* Module name */
\r
54 CHAR trackername[20]; /* Tracker name */
\r
55 UWORD version; /* Version number */
\r
56 ULONG headersize; /* Header size */
\r
57 UWORD songlength; /* Song length (in patten order table) */
\r
58 UWORD restart; /* Restart position */
\r
59 UWORD numchn; /* Number of channels (2,4,6,8,10,...,32) */
\r
60 UWORD numpat; /* Number of patterns (max 256) */
\r
61 UWORD numins; /* Number of instruments (max 128) */
\r
63 UWORD tempo; /* Default tempo */
\r
64 UWORD bpm; /* Default BPM */
\r
65 UBYTE orders[256]; /* Pattern order table */
\r
68 typedef struct XMINSTHEADER {
\r
69 ULONG size; /* Instrument size */
\r
70 CHAR name[22]; /* Instrument name */
\r
71 UBYTE type; /* Instrument type (always 0) */
\r
72 UWORD numsmp; /* Number of samples in instrument */
\r
76 #define XMENVCNT (12*2)
\r
77 #define XMNOTECNT (8*OCTAVE)
\r
78 typedef struct XMPATCHHEADER {
\r
79 UBYTE what[XMNOTECNT]; /* Sample number for all notes */
\r
80 UWORD volenv[XMENVCNT]; /* Points for volume envelope */
\r
81 UWORD panenv[XMENVCNT]; /* Points for panning envelope */
\r
82 UBYTE volpts; /* Number of volume points */
\r
83 UBYTE panpts; /* Number of panning points */
\r
84 UBYTE volsus; /* Volume sustain point */
\r
85 UBYTE volbeg; /* Volume loop start point */
\r
86 UBYTE volend; /* Volume loop end point */
\r
87 UBYTE pansus; /* Panning sustain point */
\r
88 UBYTE panbeg; /* Panning loop start point */
\r
89 UBYTE panend; /* Panning loop end point */
\r
90 UBYTE volflg; /* Volume type: bit 0: On; 1: Sustain; 2: Loop */
\r
91 UBYTE panflg; /* Panning type: bit 0: On; 1: Sustain; 2: Loop */
\r
92 UBYTE vibflg; /* Vibrato type */
\r
93 UBYTE vibsweep; /* Vibrato sweep */
\r
94 UBYTE vibdepth; /* Vibrato depth */
\r
95 UBYTE vibrate; /* Vibrato rate */
\r
96 UWORD volfade; /* Volume fadeout */
\r
99 typedef struct XMWAVHEADER {
\r
100 ULONG length; /* Sample length */
\r
101 ULONG loopstart; /* Sample loop start */
\r
102 ULONG looplength; /* Sample loop length */
\r
103 UBYTE volume; /* Volume */
\r
104 SBYTE finetune; /* Finetune (signed byte -128..+127) */
\r
105 UBYTE type; /* Loop type */
\r
106 UBYTE panning; /* Panning (0-255) */
\r
107 SBYTE relnote; /* Relative note number (signed byte) */
\r
109 CHAR samplename[22]; /* Sample name */
\r
110 UBYTE vibtype; /* Vibrato type */
\r
111 UBYTE vibsweep; /* Vibrato sweep */
\r
112 UBYTE vibdepth; /* Vibrato depth */
\r
113 UBYTE vibrate; /* Vibrato rate */
\r
116 typedef struct XMPATHEADER {
\r
117 ULONG size; /* Pattern header length */
\r
118 UBYTE packing; /* Packing type (always 0) */
\r
119 UWORD numrows; /* Number of rows in pattern (1..256) */
\r
120 SWORD packsize; /* Packed patterndata size */
\r
123 typedef struct XMNOTE {
\r
124 UBYTE note,ins,vol,eff,dat;
\r
127 /*========== Loader variables */
\r
129 static XMNOTE *xmpat=NULL;
\r
130 static XMHEADER *mh=NULL;
\r
132 /* increment unit for sample array reallocation */
\r
133 #define XM_SMPINCR 64
\r
134 static ULONG *nextwav=NULL;
\r
135 static XMWAVHEADER *wh=NULL,*s=NULL;
\r
137 /*========== Loader code */
\r
143 if(!_mm_read_UBYTES(id,38,modreader)) return 0;
\r
144 if(memcmp(id,"Extended Module: ",17)) return 0;
\r
145 if(id[37]==0x1a) return 1;
\r
151 if(!(mh=(XMHEADER *)_mm_malloc(sizeof(XMHEADER)))) return 0;
\r
155 void XM_Cleanup(void)
\r
160 static int XM_ReadNote(XMNOTE* n)
\r
162 UBYTE cmp,result=1;
\r
164 memset(n,0,sizeof(XMNOTE));
\r
165 cmp=_mm_read_UBYTE(modreader);
\r
168 if(cmp&1) { result++;n->note = _mm_read_UBYTE(modreader); }
\r
169 if(cmp&2) { result++;n->ins = _mm_read_UBYTE(modreader); }
\r
170 if(cmp&4) { result++;n->vol = _mm_read_UBYTE(modreader); }
\r
171 if(cmp&8) { result++;n->eff = _mm_read_UBYTE(modreader); }
\r
172 if(cmp&16) { result++;n->dat = _mm_read_UBYTE(modreader); }
\r
175 n->ins = _mm_read_UBYTE(modreader);
\r
176 n->vol = _mm_read_UBYTE(modreader);
\r
177 n->eff = _mm_read_UBYTE(modreader);
\r
178 n->dat = _mm_read_UBYTE(modreader);
\r
184 static UBYTE* XM_Convert(XMNOTE* xmtrack,UWORD rows)
\r
187 UBYTE note,ins,vol,eff,dat;
\r
190 for(t=0;t<rows;t++) {
\r
191 note = xmtrack->note;
\r
192 ins = xmtrack->ins;
\r
193 vol = xmtrack->vol;
\r
194 eff = xmtrack->eff;
\r
195 dat = xmtrack->dat;
\r
199 UniEffect(UNI_KEYFADE,0);
\r
203 if(ins) UniInstrument(ins-1);
\r
206 case 0x6: /* volslide down */
\r
207 if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol&0xf);
\r
209 case 0x7: /* volslide up */
\r
210 if(vol&0xf) UniEffect(UNI_XMEFFECTA,vol<<4);
\r
213 /* volume-row fine volume slide is compatible with protracker
\r
214 EBx and EAx effects i.e. a zero nibble means DO NOT SLIDE, as
\r
215 opposed to 'take the last sliding value'. */
\r
216 case 0x8: /* finevol down */
\r
217 UniPTEffect(0xe,0xb0|(vol&0xf));
\r
219 case 0x9: /* finevol up */
\r
220 UniPTEffect(0xe,0xa0|(vol&0xf));
\r
222 case 0xa: /* set vibrato speed */
\r
223 UniEffect(UNI_XMEFFECT4,vol<<4);
\r
225 case 0xb: /* vibrato */
\r
226 UniEffect(UNI_XMEFFECT4,vol&0xf);
\r
228 case 0xc: /* set panning */
\r
229 UniPTEffect(0x8,vol<<4);
\r
231 case 0xd: /* panning slide left (only slide when data not zero) */
\r
232 if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol&0xf);
\r
234 case 0xe: /* panning slide right (only slide when data not zero) */
\r
235 if(vol&0xf) UniEffect(UNI_XMEFFECTP,vol<<4);
\r
237 case 0xf: /* tone porta */
\r
238 UniPTEffect(0x3,vol<<4);
\r
241 if((vol>=0x10)&&(vol<=0x50))
\r
242 UniPTEffect(0xc,vol-0x10);
\r
247 UniEffect(UNI_XMEFFECT4,dat);
\r
250 UniEffect(UNI_XMEFFECT6,dat);
\r
253 UniEffect(UNI_XMEFFECTA,dat);
\r
255 case 0xe: /* Extended effects */
\r
257 case 0x1: /* XM fine porta up */
\r
258 UniEffect(UNI_XMEFFECTE1,dat&0xf);
\r
260 case 0x2: /* XM fine porta down */
\r
261 UniEffect(UNI_XMEFFECTE2,dat&0xf);
\r
263 case 0xa: /* XM fine volume up */
\r
264 UniEffect(UNI_XMEFFECTEA,dat&0xf);
\r
266 case 0xb: /* XM fine volume down */
\r
267 UniEffect(UNI_XMEFFECTEB,dat&0xf);
\r
270 UniPTEffect(eff,dat);
\r
273 case 'G'-55: /* G - set global volume */
\r
274 UniEffect(UNI_XMEFFECTG,dat>64?128:dat<<1);
\r
276 case 'H'-55: /* H - global volume slide */
\r
277 UniEffect(UNI_XMEFFECTH,dat);
\r
279 case 'K'-55: /* K - keyOff and KeyFade */
\r
280 UniEffect(UNI_KEYFADE,dat);
\r
282 case 'L'-55: /* L - set envelope position */
\r
283 UniEffect(UNI_XMEFFECTL,dat);
\r
285 case 'P'-55: /* P - panning slide */
\r
286 UniEffect(UNI_XMEFFECTP,dat);
\r
288 case 'R'-55: /* R - multi retrig note */
\r
289 UniEffect(UNI_S3MEFFECTQ,dat);
\r
291 case 'T'-55: /* T - Tremor */
\r
292 UniEffect(UNI_S3MEFFECTI,dat);
\r
296 case 1: /* X1 - Extra Fine Porta up */
\r
297 UniEffect(UNI_XMEFFECTX1,dat&0xf);
\r
299 case 2: /* X2 - Extra Fine Porta down */
\r
300 UniEffect(UNI_XMEFFECTX2,dat&0xf);
\r
306 /* the pattern jump destination is written in decimal,
\r
307 but it seems some poor tracker software writes them
\r
308 in hexadecimal... (sigh) */
\r
310 /* don't change anything if we're sure it's in hexa */
\r
311 if ((((dat&0xf0)>>4)<=9)&&((dat&0xf)<=9))
\r
312 /* otherwise, convert from dec to hex */
\r
313 dat=(((dat&0xf0)>>4)*10)+(dat&0xf);
\r
314 UniPTEffect(eff,dat);
\r
324 static BOOL LoadPatterns(BOOL dummypat)
\r
328 if(!AllocTracks()) return 0;
\r
329 if(!AllocPatterns()) return 0;
\r
332 for(t=0;t<mh->numpat;t++) {
\r
335 ph.size =_mm_read_I_ULONG(modreader);
\r
336 if (ph.size<(mh->version==0x0102?8:9)) {
\r
337 _mm_errno=MMERR_LOADING_PATTERN;
\r
340 ph.packing =_mm_read_UBYTE(modreader);
\r
342 _mm_errno=MMERR_LOADING_PATTERN;
\r
345 if(mh->version==0x0102)
\r
346 ph.numrows =_mm_read_UBYTE(modreader)+1;
\r
348 ph.numrows =_mm_read_I_UWORD(modreader);
\r
349 ph.packsize =_mm_read_I_UWORD(modreader);
\r
351 ph.size-=(mh->version==0x0102?8:9);
\r
353 _mm_fseek(modreader,ph.size,SEEK_CUR);
\r
355 of.pattrows[t]=ph.numrows;
\r
358 if(!(xmpat=(XMNOTE*)_mm_calloc(ph.numrows*of.numchn,sizeof(XMNOTE))))
\r
361 /* when packsize is 0, don't try to load a pattern.. it's empty. */
\r
363 for(u=0;u<ph.numrows;u++)
\r
364 for(v=0;v<of.numchn;v++) {
\r
365 if(!ph.packsize) break;
\r
367 ph.packsize-=XM_ReadNote(&xmpat[(v*ph.numrows)+u]);
\r
368 if(ph.packsize<0) {
\r
369 free(xmpat);xmpat=NULL;
\r
370 _mm_errno=MMERR_LOADING_PATTERN;
\r
376 _mm_fseek(modreader,ph.packsize,SEEK_CUR);
\r
379 if(_mm_eof(modreader)) {
\r
380 free(xmpat);xmpat=NULL;
\r
381 _mm_errno=MMERR_LOADING_PATTERN;
\r
385 for(v=0;v<of.numchn;v++)
\r
386 of.tracks[numtrk++]=XM_Convert(&xmpat[v*ph.numrows],ph.numrows);
\r
388 free(xmpat);xmpat=NULL;
\r
390 for(v=0;v<of.numchn;v++)
\r
391 of.tracks[numtrk++]=XM_Convert(NULL,ph.numrows);
\r
397 if(!(xmpat=(XMNOTE*)_mm_calloc(64*of.numchn,sizeof(XMNOTE)))) return 0;
\r
398 for(v=0;v<of.numchn;v++)
\r
399 of.tracks[numtrk++]=XM_Convert(&xmpat[v*64],64);
\r
400 free(xmpat);xmpat=NULL;
\r
406 static void FixEnvelope(ENVPT *cur, int pts)
\r
411 /* Some broken XM editing program will only save the low byte
\r
412 of the position value. Try to compensate by adding the
\r
413 missing high byte. */
\r
418 for (u = 1; u < pts; u++, prev++, cur++) {
\r
419 if (cur->pos < prev->pos) {
\r
420 if (cur->pos < 0x100) {
\r
421 if (cur->pos > old) /* same hex century */
\r
422 tmp = cur->pos + (prev->pos - old);
\r
424 tmp = cur->pos | ((prev->pos + 0x100) & 0xff00);
\r
427 #ifdef MIKMOD_DEBUG
\r
428 fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d -> %d\n",
\r
429 u, pts, prev->pos, old, cur->pos);
\r
432 #ifdef MIKMOD_DEBUG
\r
433 /* different brokenness style... fix unknown */
\r
434 fprintf(stderr, "\rbroken envelope position(%d/%d), %d %d\n",
\r
435 u, pts, old, cur->pos);
\r
444 static BOOL LoadInstruments(void)
\r
451 if(!AllocInstruments()) return 0;
\r
453 for(t=0;t<of.numins;t++,d++) {
\r
457 memset(d->samplenumber,0xff,INSTNOTES*sizeof(UWORD));
\r
459 /* read instrument header */
\r
460 headend = _mm_ftell(modreader);
\r
461 ih.size = _mm_read_I_ULONG(modreader);
\r
462 headend += ih.size;
\r
463 _mm_read_string(ih.name, 22, modreader);
\r
464 ih.type = _mm_read_UBYTE(modreader);
\r
465 ih.numsmp = _mm_read_I_UWORD(modreader);
\r
467 d->insname = DupStr(ih.name,22,1);
\r
469 if((SWORD)ih.size>29) {
\r
470 ih.ssize = _mm_read_I_ULONG(modreader);
\r
471 if(((SWORD)ih.numsmp>0)&&(ih.numsmp<=XMNOTECNT)) {
\r
475 _mm_read_UBYTES (pth.what,XMNOTECNT,modreader);
\r
476 _mm_read_I_UWORDS (pth.volenv, XMENVCNT, modreader);
\r
477 _mm_read_I_UWORDS (pth.panenv, XMENVCNT, modreader);
\r
478 pth.volpts = _mm_read_UBYTE(modreader);
\r
479 pth.panpts = _mm_read_UBYTE(modreader);
\r
480 pth.volsus = _mm_read_UBYTE(modreader);
\r
481 pth.volbeg = _mm_read_UBYTE(modreader);
\r
482 pth.volend = _mm_read_UBYTE(modreader);
\r
483 pth.pansus = _mm_read_UBYTE(modreader);
\r
484 pth.panbeg = _mm_read_UBYTE(modreader);
\r
485 pth.panend = _mm_read_UBYTE(modreader);
\r
486 pth.volflg = _mm_read_UBYTE(modreader);
\r
487 pth.panflg = _mm_read_UBYTE(modreader);
\r
488 pth.vibflg = _mm_read_UBYTE(modreader);
\r
489 pth.vibsweep = _mm_read_UBYTE(modreader);
\r
490 pth.vibdepth = _mm_read_UBYTE(modreader);
\r
491 pth.vibrate = _mm_read_UBYTE(modreader);
\r
492 pth.volfade = _mm_read_I_UWORD(modreader);
\r
494 /* read the remainder of the header
\r
495 (2 bytes for 1.03, 22 for 1.04) */
\r
496 for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
\r
498 /* we can't trust the envelope point count here, as some
\r
499 modules have incorrect values (K_OSPACE.XM reports 32 volume
\r
500 points, for example). */
\r
501 if(pth.volpts>XMENVCNT/2) pth.volpts=XMENVCNT/2;
\r
502 if(pth.panpts>XMENVCNT/2) pth.panpts=XMENVCNT/2;
\r
504 if((_mm_eof(modreader))||(pth.volpts>XMENVCNT/2)||(pth.panpts>XMENVCNT/2)) {
\r
505 if(nextwav) { free(nextwav);nextwav=NULL; }
\r
506 if(wh) { free(wh);wh=NULL; }
\r
507 _mm_errno = MMERR_LOADING_SAMPLEINFO;
\r
511 for(u=0;u<XMNOTECNT;u++)
\r
512 d->samplenumber[u]=pth.what[u]+of.numsmp;
\r
513 d->volfade = pth.volfade;
\r
515 #if defined __STDC__ || defined _MSC_VER || defined MPW_C
\r
516 #define XM_ProcessEnvelope(name) \
\r
517 for (u = 0; u < (XMENVCNT >> 1); u++) { \
\r
518 d-> name##env[u].pos = pth. name##env[u << 1]; \
\r
519 d-> name##env[u].val = pth. name##env[(u << 1)+ 1]; \
\r
521 if (pth. name##flg&1) d-> name##flg|=EF_ON; \
\r
522 if (pth. name##flg&2) d-> name##flg|=EF_SUSTAIN; \
\r
523 if (pth. name##flg&4) d-> name##flg|=EF_LOOP; \
\r
524 d-> name##susbeg=d-> name##susend=pth. name##sus; \
\r
525 d-> name##beg=pth. name##beg; \
\r
526 d-> name##end=pth. name##end; \
\r
527 d-> name##pts=pth. name##pts; \
\r
529 /* scale envelope */ \
\r
530 for (p=0;p<XMENVCNT/2;p++) \
\r
531 d-> name##env[p].val<<=2; \
\r
533 if ((d-> name##flg&EF_ON)&&(d-> name##pts<2)) \
\r
534 d-> name##flg&=~EF_ON
\r
536 #define XM_ProcessEnvelope(name) \
\r
537 for (u = 0; u < (XMENVCNT >> 1); u++) { \
\r
538 d-> name/**/env[u].pos = pth. name/**/env[u << 1]; \
\r
539 d-> name/**/env[u].val = pth. name/**/env[(u << 1)+ 1]; \
\r
541 if (pth. name/**/flg&1) d-> name/**/flg|=EF_ON; \
\r
542 if (pth. name/**/flg&2) d-> name/**/flg|=EF_SUSTAIN; \
\r
543 if (pth. name/**/flg&4) d-> name/**/flg|=EF_LOOP; \
\r
544 d-> name/**/susbeg=d-> name/**/susend= \
\r
545 pth. name/**/sus; \
\r
546 d-> name/**/beg=pth. name/**/beg; \
\r
547 d-> name/**/end=pth. name/**/end; \
\r
548 d-> name/**/pts=pth. name/**/pts; \
\r
550 /* scale envelope */ \
\r
551 for (p=0;p<XMENVCNT/2;p++) \
\r
552 d-> name/**/env[p].val<<=2; \
\r
554 if ((d-> name/**/flg&EF_ON)&&(d-> name/**/pts<2)) \
\r
555 d-> name/**/flg&=~EF_ON
\r
558 XM_ProcessEnvelope(vol);
\r
559 XM_ProcessEnvelope(pan);
\r
560 #undef XM_ProcessEnvelope
\r
562 if (d->volflg & EF_ON)
\r
563 FixEnvelope(d->volenv, d->volpts);
\r
564 if (d->panflg & EF_ON)
\r
565 FixEnvelope(d->panenv, d->panpts);
\r
567 /* Samples are stored outside the instrument struct now, so we
\r
568 have to load them all into a temp area, count the of.numsmp
\r
569 along the way and then do an AllocSamples() and move
\r
571 if(mh->version>0x0103) next = 0;
\r
572 for(u=0;u<ih.numsmp;u++,s++) {
\r
573 /* Allocate more room for sample information if necessary */
\r
574 if(of.numsmp+u==wavcnt) {
\r
575 wavcnt+=XM_SMPINCR;
\r
576 if(!(nextwav=realloc(nextwav,wavcnt*sizeof(ULONG)))){
\r
577 if(wh) { free(wh);wh=NULL; }
\r
578 _mm_errno = MMERR_OUT_OF_MEMORY;
\r
581 if(!(wh=realloc(wh,wavcnt*sizeof(XMWAVHEADER)))) {
\r
582 free(nextwav);nextwav=NULL;
\r
583 _mm_errno = MMERR_OUT_OF_MEMORY;
\r
586 s=wh+(wavcnt-XM_SMPINCR);
\r
589 s->length =_mm_read_I_ULONG (modreader);
\r
590 s->loopstart =_mm_read_I_ULONG (modreader);
\r
591 s->looplength =_mm_read_I_ULONG (modreader);
\r
592 s->volume =_mm_read_UBYTE (modreader);
\r
593 s->finetune =_mm_read_SBYTE (modreader);
\r
594 s->type =_mm_read_UBYTE (modreader);
\r
595 s->panning =_mm_read_UBYTE (modreader);
\r
596 s->relnote =_mm_read_SBYTE (modreader);
\r
597 s->vibtype = pth.vibflg;
\r
598 s->vibsweep = pth.vibsweep;
\r
599 s->vibdepth = pth.vibdepth*4;
\r
600 s->vibrate = pth.vibrate;
\r
601 s->reserved =_mm_read_UBYTE (modreader);
\r
602 _mm_read_string(s->samplename, 22, modreader);
\r
604 nextwav[of.numsmp+u]=next;
\r
607 if(_mm_eof(modreader)) {
\r
608 free(nextwav);free(wh);
\r
609 nextwav=NULL;wh=NULL;
\r
610 _mm_errno = MMERR_LOADING_SAMPLEINFO;
\r
615 if(mh->version>0x0103) {
\r
616 for(u=0;u<ih.numsmp;u++)
\r
617 nextwav[of.numsmp++]+=_mm_ftell(modreader);
\r
618 _mm_fseek(modreader,next,SEEK_CUR);
\r
620 of.numsmp+=ih.numsmp;
\r
622 /* read the remainder of the header */
\r
623 for(u=headend-_mm_ftell(modreader);u;u--) _mm_read_UBYTE(modreader);
\r
625 if(_mm_eof(modreader)) {
\r
626 free(nextwav);free(wh);
\r
627 nextwav=NULL;wh=NULL;
\r
628 _mm_errno = MMERR_LOADING_SAMPLEINFO;
\r
637 if(nextwav) { free(nextwav);nextwav=NULL; }
\r
638 if(wh) { free(wh);wh=NULL; }
\r
639 _mm_errno = MMERR_LOADING_SAMPLEINFO;
\r
646 BOOL XM_Load(BOOL curious)
\r
652 char tracker[21],modtype[60];
\r
655 /* try to read module header */
\r
656 _mm_read_string(mh->id,17,modreader);
\r
657 _mm_read_string(mh->songname,21,modreader);
\r
658 _mm_read_string(mh->trackername,20,modreader);
\r
659 mh->version =_mm_read_I_UWORD(modreader);
\r
660 if((mh->version<0x102)||(mh->version>0x104)) {
\r
661 _mm_errno=MMERR_NOT_A_MODULE;
\r
664 mh->headersize =_mm_read_I_ULONG(modreader);
\r
665 mh->songlength =_mm_read_I_UWORD(modreader);
\r
666 mh->restart =_mm_read_I_UWORD(modreader);
\r
667 mh->numchn =_mm_read_I_UWORD(modreader);
\r
668 mh->numpat =_mm_read_I_UWORD(modreader);
\r
669 mh->numins =_mm_read_I_UWORD(modreader);
\r
670 mh->flags =_mm_read_I_UWORD(modreader);
\r
671 mh->tempo =_mm_read_I_UWORD(modreader);
\r
672 mh->bpm =_mm_read_I_UWORD(modreader);
\r
674 _mm_errno=MMERR_NOT_A_MODULE;
\r
677 _mm_read_UBYTES(mh->orders,256,modreader);
\r
679 if(_mm_eof(modreader)) {
\r
680 _mm_errno = MMERR_LOADING_HEADER;
\r
684 /* set module variables */
\r
685 of.initspeed = mh->tempo;
\r
686 of.inittempo = mh->bpm;
\r
687 strncpy(tracker,mh->trackername,20);tracker[20]=0;
\r
688 for(t=20;(tracker[t]<=' ')&&(t>=0);t--) tracker[t]=0;
\r
690 /* some modules have the tracker name empty */
\r
692 strcpy(tracker,"Unknown tracker");
\r
694 #ifdef HAVE_SNPRINTF
\r
695 snprintf(modtype,60,"%s (XM format %d.%02d)",
\r
696 tracker,mh->version>>8,mh->version&0xff);
\r
698 sprintf(modtype,"%s (XM format %d.%02d)",
\r
699 tracker,mh->version>>8,mh->version&0xff);
\r
701 of.modtype = strdup(modtype);
\r
702 of.numchn = mh->numchn;
\r
703 of.numpat = mh->numpat;
\r
704 of.numtrk = (UWORD)of.numpat*of.numchn; /* get number of channels */
\r
705 of.songname = DupStr(mh->songname,20,1);
\r
706 of.numpos = mh->songlength; /* copy the songlength */
\r
707 of.reppos = mh->restart<mh->songlength?mh->restart:0;
\r
708 of.numins = mh->numins;
\r
709 of.flags |= UF_XMPERIODS | UF_INST | UF_NOWRAP | UF_FT2QUIRKS |
\r
711 if(mh->flags&1) of.flags |= UF_LINEAR;
\r
714 memset(of.chanvol,64,of.numchn); /* store channel volumes */
\r
716 if(!AllocPositions(of.numpos+1)) return 0;
\r
717 for(t=0;t<of.numpos;t++)
\r
718 of.positions[t]=mh->orders[t];
\r
720 /* We have to check for any pattern numbers in the order list greater than
\r
721 the number of patterns total. If one or more is found, we set it equal to
\r
722 the pattern total and make a dummy pattern to workaround the problem */
\r
723 for(t=0;t<of.numpos;t++) {
\r
724 if(of.positions[t]>=of.numpat) {
\r
725 of.positions[t]=of.numpat;
\r
730 of.numpat++;of.numtrk+=of.numchn;
\r
733 if(mh->version<0x0104) {
\r
734 if(!LoadInstruments()) return 0;
\r
735 if(!LoadPatterns(dummypat)) return 0;
\r
736 for(t=0;t<of.numsmp;t++)
\r
737 nextwav[t]+=_mm_ftell(modreader);
\r
739 if(!LoadPatterns(dummypat)) return 0;
\r
740 if(!LoadInstruments()) return 0;
\r
743 if(!AllocSamples()) {
\r
744 free(nextwav);free(wh);
\r
745 nextwav=NULL;wh=NULL;
\r
750 for(u=0;u<of.numsmp;u++,q++,s++) {
\r
751 q->samplename = DupStr(s->samplename,22,1);
\r
752 q->length = s->length;
\r
753 q->loopstart = s->loopstart;
\r
754 q->loopend = s->loopstart+s->looplength;
\r
755 q->volume = s->volume;
\r
756 q->speed = s->finetune+128;
\r
757 q->panning = s->panning;
\r
758 q->seekpos = nextwav[u];
\r
759 q->vibtype = s->vibtype;
\r
760 q->vibsweep = s->vibsweep;
\r
761 q->vibdepth = s->vibdepth;
\r
762 q->vibrate = s->vibrate;
\r
764 if(s->type & 0x10) {
\r
766 q->loopstart >>= 1;
\r
770 q->flags|=SF_OWNPAN|SF_DELTA|SF_SIGNED;
\r
771 if(s->type&0x3) q->flags|=SF_LOOP;
\r
772 if(s->type&0x2) q->flags|=SF_BIDI;
\r
773 if(s->type&0x10) q->flags|=SF_16BITS;
\r
778 for(u=0;u<of.numins;u++,d++)
\r
779 for(t=0;t<XMNOTECNT;t++) {
\r
780 if (d->samplenumber[t]>=of.numsmp)
\r
781 d->samplenote[t]=255;
\r
783 int note=t+s[d->samplenumber[t]].relnote;
\r
784 d->samplenote[t]=(note<0)?0:note;
\r
788 free(wh);free(nextwav);
\r
789 wh=NULL;nextwav=NULL;
\r
793 CHAR *XM_LoadTitle(void)
\r
797 _mm_fseek(modreader,17,SEEK_SET);
\r
798 if(!_mm_read_UBYTES(s,21,modreader)) return NULL;
\r
800 return(DupStr(s,21,1));
\r
803 /*========== Loader information */
\r
805 MIKMODAPI MLOADER load_xm={
\r
808 "XM (FastTracker 2)",
\r